Пример #1
0
        //This code draws the target distance and closest approach
        private void rightGauge()
        {
            ITargetable itarget = FlightGlobals.fetch.VesselTarget;

            if (itarget != null && itarget.GetOrbit() != null)
            {
                Vessel target = itarget.GetVessel();
                //Calculate and draw the distance between active vessal and target
                Vector3d aPos = FlightGlobals.ActiveVessel.orbit.pos;
                Vector3d tPos = itarget.GetOrbit().pos;
                //double distance = Vector3d.Distance(tPos, aPos);
                double distance = SteamShip.TargetDist;
                drawDigits(981, 131, distance);
                //Draw closure light
                if (distance < closestRed)  //red light
                {
                    GUI.DrawTextureWithTexCoords(new Rect(1014f * Scale, 101f * Scale, 17f * Scale, 17f * Scale), texture, new Rect(0.5058f, 0.2625f, 0.0142f, 0.0142f));
                }
                else if (distance < closestYellow)   //yellow light
                {
                    GUI.DrawTextureWithTexCoords(new Rect(1014f * Scale, 101f * Scale, 17f * Scale, 17f * Scale), texture, new Rect(0.5225f, 0.2625f, 0.0142f, 0.0142f));
                }
                else if (distance < closestGreen)   //green light
                {
                    GUI.DrawTextureWithTexCoords(new Rect(1014f * Scale, 101f * Scale, 17f * Scale, 17f * Scale), texture, new Rect(0.4875f, 0.2625f, 0.0142f, 0.0142f));
                }

                //Crunch closest distance, and display
                //res Result = getClosestApproach();
                drawDigits(982, 197, SteamShip.ClosestApproach);
                drawTime(1019, 260, SteamShip.ClosestTime);
                //Maybe surround this gauge with a AN/DN offset?
            }
        }
Пример #2
0
 /// <summary>
 /// Return the body to search for destinations next after the parameter.
 /// Essentially a wrapper around CelestialBody.referenceBody to make it
 /// return null for the sun instead of itself.
 /// </summary>
 /// <param name="target">Previous target we searched</param>
 public static CelestialBody ParentBody(ITargetable target)
 {
     if (target.GetOrbit() == null || target.GetOrbit().referenceBody == target as CelestialBody)
     {
         return(null);
     }
     else
     {
         return(target.GetOrbit().referenceBody);
     }
 }
Пример #3
0
 public string findNameForOrbit(Orbit orbit, ITargetable start)
 {
     if (start.GetOrbit() == orbit || start.GetOrbit() == null)
     {
         return(start.GetName());
     }
     else
     {
         return(findNameForOrbit(orbit, start.GetOrbit().referenceBody));
     }
 }
Пример #4
0
        private void relAsc()
        {
            if (_patch == null || _patch.referenceBody == null)
            {
                return;
            }

            //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 1);

            ITargetable tgt = FlightGlobals.fetch.VesselTarget;

            if (tgt == null || tgt.GetOrbit() == null || tgt.GetOrbit().referenceBody == null)
            {
                return;
            }

            //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 2);

            if (_patch.referenceBody != tgt.GetOrbit().referenceBody)
            {
                return;
            }

            //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 3);

            double relAsc = ManeuverUtilities.RelAscTime(_patch, tgt);

            if (_patch.UTsoi > 0 && relAsc > _patch.UTsoi)
            {
                return;
            }
            else if (relAsc < Planetarium.GetUniversalTime())
            {
                return;
            }
            else
            {
                //ManeuverController.maneuverLog("Rel Asc: {0}", logLevels.log, 4);

                double periods = 0;

                if (!double.IsNaN(_patch.period) && !double.IsInfinity(_patch.period))
                {
                    periods = (_orbitsAdded * _patch.period);
                }

                setNodeTime(relAsc + periods);
            }
        }
Пример #5
0
        internal static Orbit getTargetOrbit(CelestialBody refbody)
        {
            ITargetable tgt = FlightGlobals.fetch.VesselTarget;

            if (tgt == null || FlightGlobals.ActiveVessel == tgt.GetVessel())
            {
                return(null);
            }

            Orbit o = tgt.GetOrbit();

            if (o.referenceBody == refbody)
            {
                return(o);
            }

            while (o.nextPatch != null)
            {
                if (o.isClosed())
                {
                    return(null);
                }
                o = o.nextPatch;
                if (o.referenceBody == refbody)
                {
                    return(o);
                }
            }
            return(null);
        }
        /// <summary>
        /// Update the current target.
        /// </summary>
        /// <param name="vessel"></param>
        private void RefreshTarget(Vessel vessel)
        {
            // Do we have a target?
            ITargetable target = vessel.targetObject;

            if (target == null)
            {
                targetOrbitalPeriod = double.NaN;
                return;
            }

            // We have a target. If it's a vessel, is it non-orbiting?
            Vessel targetVessel = target.GetVessel();

            if ((targetVessel != null) && (targetVessel.situation != Vessel.Situations.ORBITING))
            {
                targetOrbitalPeriod = double.NaN;
                return;
            }

            // It's something else.  Could be an orbiting vessel, could be a celestial body,
            // could be some other ITargetable (which I believe doesn't exist in the stock
            // game, but mods could introduce other types).  Does it have an orbit?
            Orbit orbit = target.GetOrbit();

            targetOrbitalPeriod = (orbit == null) ? double.NaN : orbit.period;
        }
Пример #7
0
        /// <summary>
        /// Make the map view focus move to the given body.
        /// Borrowed and modified from Precise Node.
        /// </summary>
        /// <param name="center">The body or vessel to put at the middle of the screen</param>
        /// <param name="edge">A body or vessel to keep barely visible when we zoom</param>
        public static void FocusMap(ITargetable center, ITargetable edge = null)
        {
            MapView.MapCamera.SetTarget(
                PlanetariumCamera.fetch.targets.Find(
                    mapObj => mapObj.celestialBody != null &&
                    mapObj.celestialBody.Equals(center)
                    )
                );

            // Zoom the camera to facilitate the next step.
            if (edge != null)
            {
                // Without an encounter, the next step is establishing the encounter within the transfer SOI.
                SetMapZoom((float)edge.GetOrbit().semiMajorAxis);
            }
            else
            {
                // With an encounter, the next step is fine tuning within the destination SOI.
                CelestialBody b = center as CelestialBody;
                if (b != null)
                {
                    SetMapZoom((float)b.sphereOfInfluence);
                }
            }
        }
Пример #8
0
        private void UpdateTarget()
        {
            activeTarget = FlightGlobals.fetch.VesselTarget;
            if (activeTarget != null)
            {
                targetDisplacement = activeTarget.GetTransform().position - vessel.GetTransform().position;
                targetDirection    = targetDisplacement.normalized;

                targetRelativeVelocity = vessel.obt_velocity - activeTarget.GetObtVelocity();
                targetCmpSpeed         = -1.0;
                targetDockingTransform = null;

                if (activeTarget is Vessel)
                {
                    targetType = ((activeTarget as Vessel).vesselType == VesselType.SpaceObject) ? TargetType.Asteroid : TargetType.Vessel;
                }
                else if (activeTarget is CelestialBody)
                {
                    targetType = TargetType.CelestialBody;
                }
                else if (activeTarget is ModuleDockingNode)
                {
                    targetType             = TargetType.DockingPort;
                    targetDockingTransform = (activeTarget as ModuleDockingNode).GetTransform();
                }
                else if (activeTarget is PositionTarget)
                {
                    targetType = TargetType.PositionTarget;
                }
                else
                {
                    Utility.LogError(this, "UpdateTarget() - unable to classify target {0}", activeTarget.GetType().Name);
                    targetType = TargetType.None;
                }

                if (targetType == TargetType.Vessel || targetType == TargetType.DockingPort)
                {
                    UpdateTargetDockingPorts();
                }

                targetName  = activeTarget.GetName();
                targetOrbit = activeTarget.GetOrbit();
            }
            else
            {
                targetCmpSpeed         = 0.0;
                targetType             = TargetType.None;
                targetDisplacement     = Vector3.zero;
                targetRelativeVelocity = Vector3d.zero;
                targetDirection        = forward;
                targetDockingTransform = null;
                targetName             = string.Empty;
                targetOrbit            = null;
                if (targetDockingPorts.Length > 0)
                {
                    targetDockingPorts = new ModuleDockingNode[0];
                }
            }
            approachSolver.ResetComputation();
        }
Пример #9
0
        /// <summary>
        /// Check whether a burn from one target to another constitutes a same-SOI transfer
        /// </summary>
        /// <param name="start">The body from which we start</param>
        /// <param name="end">The body where we end up</param>
        /// <returns>
        /// True if same SOI transfer, false if an ejection angle is involved
        /// </returns>
        public static bool SameSOITransfer(ITargetable start, ITargetable end)
        {
            CelestialBody b1 = start as CelestialBody;

            if (b1 != null)
            {
                // 1. start is body,   end is body:   end's referenceBody must be start
                // 2. start is body,   end is vessel: N/A - bodies can't have targets
                return(b1 == end.GetOrbit().referenceBody);
            }
            else
            {
                // 3. start is vessel, end is vessel: Orbits must have same referenceBody
                // 4. start is vessel, end is body:   Orbits must have same referenceBody
                // This needs to treat solar orbit -> Laythe as same SOI!
                return(AncestorsInclude(end.GetOrbit().referenceBody, start.GetOrbit().referenceBody));
            }
        }
Пример #10
0
        //Code fully by me
        //Come to within 150m of the target
        void RenezvousWithTarget(ITargetable target, Vessel attackVessel)
        {
            var oDriver = attackVessel.orbitDriver;
            var tOrbit  = target.GetOrbit();

            HardsetOrbit(oDriver, tOrbit);
            attackVessel.GoOffRails();
            target.GetVessel().GoOffRails();
        }
Пример #11
0
        public static bool TargetValid()
        {
            if (FlightGlobals.ActiveVessel == null ||
                FlightGlobals.ActiveVessel.targetObject == null ||
                FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null ||
                FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody == null ||
                FlightGlobals.ActiveVessel.orbit == null ||
                FlightGlobals.ActiveVessel.orbit.referenceBody == null)
            {
                _targetBody      = null;
                _vesselIntersect = false;
                _bodyIntersect   = false;
                _updated         = false;
                _activeVessel    = null;
                _activeBody      = null;
                _targetObject    = null;
                _targetTransform = null;
                return(false);
            }

            _activeVessel = FlightGlobals.ActiveVessel;
            _activeBody   = FlightGlobals.currentMainBody;
            _targetObject = _activeVessel.targetObject;

            if (_targetObject.GetVessel() == null)
            {
                if (_targetObject.GetOrbit() == null)
                {
                    _targetBody  = null;
                    _isCelestial = false;
                    _isVessel    = false;
                }
                else if (_targetObject.GetOrbitDriver().celestialBody != null)
                {
                    _targetBody  = _targetObject.GetOrbitDriver().celestialBody;
                    _isCelestial = true;
                    _isVessel    = false;
                }
                else
                {
                    _targetBody  = null;
                    _isCelestial = false;
                    _isVessel    = false;
                }
            }
            else
            {
                _targetBody        = null;
                _isCelestial       = false;
                _isVessel          = true;
                _targetTransform   = FlightGlobals.fetch.vesselTargetTransform;
                _vesselTargetDelta = FlightGlobals.fetch.vesselTargetDelta;
            }

            return(true);
        }
Пример #12
0
        /// <summary>
        /// Returns the orbit of the currently targeted item or null if there is none.
        /// </summary>
        /// <returns>The orbit or null.</returns>
        public static Orbit getTargetOrbit()
        {
            ITargetable tgt = FlightGlobals.fetch.VesselTarget;

            if (tgt != null)
            {
                // if we have a null vessel it's a celestial body
                if (tgt.GetVessel() == null)
                {
                    return(tgt.GetOrbit());
                }
                // otherwise make sure we're not targeting ourselves.
                if (!FlightGlobals.fetch.activeVessel.Equals(tgt.GetVessel()))
                {
                    return(tgt.GetOrbit());
                }
            }
            return(null);
        }
Пример #13
0
        private void relDesc()
        {
            if (_patch == null || _patch.referenceBody == null)
            {
                return;
            }

            ITargetable tgt = FlightGlobals.fetch.VesselTarget;

            if (tgt == null || tgt.GetOrbit() == null || tgt.GetOrbit().referenceBody == null)
            {
                return;
            }

            if (_patch.referenceBody != tgt.GetOrbit().referenceBody)
            {
                return;
            }

            double relDesc = ManeuverUtilities.RelDescTime(_patch, tgt);

            if (_patch.UTsoi > 0 && relDesc > _patch.UTsoi)
            {
                return;
            }
            else if (relDesc < Planetarium.GetUniversalTime())
            {
                return;
            }
            else
            {
                double periods = 0;

                if (!double.IsNaN(_patch.period) && !double.IsInfinity(_patch.period))
                {
                    periods = (_orbitsAdded * _patch.period);
                }

                setNodeTime(relDesc + periods);
            }
        }
Пример #14
0
        private void clApp()
        {
            if (_patch == null)
            {
                return;
            }

            ITargetable tgt = FlightGlobals.fetch.VesselTarget;

            if (tgt == null)
            {
                return;
            }

            double clApp = 0;

            if (tgt.GetVessel() == null)
            {
                clApp = _patch.closestTgtApprUT;
            }
            else
            {
                clApp = ManeuverUtilities.closestVessel(0, _patch, tgt.GetOrbit(), true, 0, 0);
            }

            if (clApp <= 0)
            {
                return;
            }

            if (_patch.UTsoi > 0 && clApp > _patch.UTsoi)
            {
                return;
            }
            else if (clApp < Planetarium.GetUniversalTime())
            {
                return;
            }
            else
            {
                setNodeTime(clApp);
            }
        }
Пример #15
0
        public static double RelDescTime(Orbit o, ITargetable tgt)
        {
            Vector3d node = Vector3d.Cross(o.GetOrbitNormal(), tgt.GetOrbit().GetOrbitNormal());

            double anomaly = o.GetTrueAnomalyOfZupVector(node);

            double period = 0;

            if (!double.IsNaN(o.period) && !double.IsInfinity(o.period))
            {
                period = o.period;
            }

            double relDesc = o.GetDTforTrueAnomaly(anomaly, period);

            if (relDesc < 0)
            {
                relDesc += period;
            }

            return(relDesc + o.StartUT);
        }
        private void WindowLayout_AddPane_TargetDistance()
        {
            intAddDistanceHeight = 262;// 272;
            GUILayout.BeginVertical();
            GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading);

            //What are the possible targets??
            List <ITargetable> iTargets = new List <ITargetable>();

            if (!(KACWorkerGameState.CurrentVesselTarget == null))
            {
                iTargets.Add(KACWorkerGameState.CurrentVesselTarget);   //VesselTarget
            }
            iTargets.Add(KACWorkerGameState.CurrentVessel.mainBody);    //Body we are orbiting
            if (KACWorkerGameState.SOIPointExists)
            {
                iTargets.Add(KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody);   //Body we will orbit next
            }

            if (intSelectediTarget > iTargets.Count - 1)
            {
                intSelectediTarget = 0;
            }

            intAddDistanceHeight += (iTargets.Count * 30);

            //Now give the user the choice
            GUILayout.BeginHorizontal();
            GUILayout.Label("Select Target:", KACResources.styleAddXferName);
            if (DrawRadioListVertical(ref intSelectediTarget, iTargets.Select(x => x.GetName()).ToArray()))
            {
                Log.info("Distance Target is:{0}", iTargets[intSelectediTarget].GetName());
            }
            GUILayout.EndHorizontal();

            //Set the tgt Object
            tgtSelectedDistance = iTargets[intSelectediTarget];
            string strDistanceName = "Distance";

            if (tgtSelectedDistance is CelestialBody)
            {
                strDistanceName = "Altitude";
            }

            //Ask for the target distance/altitude
            GUILayout.BeginHorizontal();
            GUILayout.Label(string.Format("Target {0} (m):", strDistanceName), KACResources.styleAddXferName);
            dblTargetDistance = Convert.ToDouble(GUILayout.TextField(dblTargetDistance.ToString(), KACResources.styleAddField));
            GUILayout.EndHorizontal();

            //If the body has an atmosphere then add an option to set the Altitude straight to that
            if (tgtSelectedDistance is CelestialBody)
            {
                if ((tgtSelectedDistance as CelestialBody).atmosphere)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(string.Format("Atmosphere: {0}", (tgtSelectedDistance as CelestialBody).atmosphereDepth));
                    if (GUILayout.Button("Set to Edge"))
                    {
                        dblTargetDistance = (tgtSelectedDistance as CelestialBody).atmosphereDepth;
                    }
                    GUILayout.EndHorizontal();
                    intAddDistanceHeight += 26;
                }
            }

            //For a vessel give some options for orbits to look forwards
            GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
            if (!(tgtSelectedDistance is CelestialBody))
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label("Orbits to Search:", KACResources.styleAddHeading, GUILayout.Width(110));
                GUILayout.Label(((int)Math.Round((Decimal)fltOrbits_Distance, 0)).ToString(), KACResources.styleAddXferName, GUILayout.Width(25));
                fltOrbits_Distance = GUILayout.HorizontalSlider(fltOrbits_Distance, 1, 20);
                fltOrbits_Distance = (float)Math.Floor((Decimal)fltOrbits_Distance);
                GUILayout.EndHorizontal();
                intAddDistanceHeight += 18;
            }

            //What VesselOrbit do we care about
            Orbit VesselOrbitToCompare = KACWorkerGameState.CurrentVessel.GetOrbit();

            if ((KACWorkerGameState.SOIPointExists) && ((tgtSelectedDistance as CelestialBody) == KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody))
            {
                VesselOrbitToCompare = KACWorkerGameState.CurrentVessel.orbit.nextPatch;
            }
            //Get the startUT of the orbit
            Double VesselOrbitStartUT = KACWorkerGameState.CurrentVessel.GetOrbit().StartUT;

            //Set up some variables
            intOrbits_Distance = (int)fltOrbits_Distance;
            int    intDistanceOrbitPass = 0;
            double dblClosestDistance   = Double.MaxValue;
            double dblDistanceUT        = 0;

            double dblOrbitTestDistance   = Double.MaxValue;
            double dblOrbitTestDistanceUT = 0;

            //If its an Altitude alarm then do this
            if (tgtSelectedDistance is CelestialBody)
            {
                dblOrbitTestDistanceUT = KACUtils.timeOfTargetAltitude(VesselOrbitToCompare,
                                                                       VesselOrbitStartUT,
                                                                       out dblOrbitTestDistance,
                                                                       dblTargetDistance
                                                                       );

                dblClosestDistance = dblOrbitTestDistance;
                dblDistanceUT      = dblOrbitTestDistanceUT;
            }
            else
            {
                //Else Iterate through the orbits to find the target separation
                for (int intOrbitToTest = 1; intOrbitToTest <= intOrbits_Distance; intOrbitToTest++)
                {
                    dblOrbitTestDistanceUT = KACUtils.timeOfTargetDistance(VesselOrbitToCompare,
                                                                           tgtSelectedDistance.GetOrbit(),
                                                                           KACWorkerGameState.CurrentTime.UT,
                                                                           intOrbitToTest,
                                                                           out dblOrbitTestDistance,
                                                                           dblTargetDistance
                                                                           );

                    if (dblOrbitTestDistance < dblClosestDistance)
                    {
                        dblClosestDistance   = dblOrbitTestDistance;
                        dblDistanceUT        = dblOrbitTestDistanceUT;
                        intDistanceOrbitPass = intOrbitToTest;
                    }
                }
            }

            //Now display what we got
            GUILayout.BeginHorizontal();
            GUILayout.Label(String.Format("{0}:", strDistanceName), KACResources.styleAddHeading, GUILayout.Width(70));
            String strDistance = string.Format("{0:#}m", dblClosestDistance);

            if (dblClosestDistance > 999)
            {
                strDistance = string.Format("{0:#.0}km", dblClosestDistance / 1000);
            }
            GUILayout.Label(strDistance, KACResources.styleAddXferName, GUILayout.Width(90));
            if (!(tgtSelectedDistance is CelestialBody))
            {
                GUILayout.Label("On Orbit:", KACResources.styleAddHeading);
                GUILayout.Label(intDistanceOrbitPass.ToString(), KACResources.styleAddXferName);
            }
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();

            //Now do the stuff to draw the alarm button
            String      strMarginConversion = "";
            KSPDateTime eventTime           = new KSPDateTime(dblDistanceUT);
            KSPTimeSpan eventInterval       = new KSPTimeSpan(dblDistanceUT - KACWorkerGameState.CurrentTime.UT);

            KSPDateTime eventAlarm;
            KSPTimeSpan eventAlarmInterval;

            try
            {
                eventAlarm         = new KSPDateTime(eventTime.UT - timeMargin.UT);
                eventAlarmInterval = new KSPTimeSpan(eventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT);
            }
            catch (Exception)
            {
                eventAlarm          = null;
                eventAlarmInterval  = null;
                strMarginConversion = "Unable to Add the Margin Minutes";
            }

            if ((eventTime.UT > KACWorkerGameState.CurrentTime.UT) && strMarginConversion == "")
            {
                if (DrawAddAlarm(eventTime, eventInterval, eventAlarmInterval))
                {
                    KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), strAlarmName, strAlarmNotes,
                                                     eventAlarm.UT, timeMargin.UT, AddType,
                                                     AddActions);
                    newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget;
                    newAlarm.ManNodes     = KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes;

                    alarms.Add(newAlarm);
                    //settings.Save();
                    _ShowAddPane = false;
                }
            }
            else
            {
                strMarginConversion = "No Target Distance Approach found";
            }

            if (strMarginConversion != "")
            {
                GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true));
            }

            GUILayout.EndVertical();
        }
Пример #17
0
        //This code draws the Apoapis, Periapsis, and Period digits onto the gauge
        private void drawAPPEP(Orbit o)
        {
            double ap = o.ApA;

            if (o.eccentricity > 1.0)
            {
                ap = 0;                  //Escape trajectory
            }
            drawDigits(181f, 132f, ap);  //Draw the Apoapsis value
            double pe = o.PeA;

            if (!showNegativePe && pe < 0)
            {
                pe = 0;                  //Don't draw negative values unless requested
            }
            drawDigits(181f, 199f, pe);  //Draw the Periapsis value

            //Time to next of: Ap, Pe, An, Dn, SoI
            double      apt = Math.Abs(o.timeToAp);
            double      pet = Math.Abs(o.timeToPe);
            double      ant = double.MaxValue;
            double      dnt = double.MaxValue;
            ITargetable tar = FlightGlobals.fetch.VesselTarget;

            if (tar != null && tar.GetOrbit() != null)
            {
                //This should prevent a few errors
                try
                {
                    ant = TimeOfAscendingNode(o, tar.GetOrbit(), Planetarium.fetch.time) - Planetarium.fetch.time;
                    dnt = TimeOfDescendingNode(o, tar.GetOrbit(), Planetarium.fetch.time) - Planetarium.fetch.time;
                }
                catch { }
            }

            //Parabolic or hyperbolic orbits don't have an apoapsis
            if (o.eccentricity > 1.0)
            {
                apt = pet;
            }
            //Also draw label on gauge
            double seconds = double.MaxValue;

            if (pet < seconds)
            {
                seconds = pet;
                next    = "pe";
            }
            if (apt < seconds)
            {
                seconds = apt;
                next    = "ap";
            }
            if (ant >= 0 && ant < seconds)
            {
                seconds = ant;
                next    = "an";
            }
            if (dnt >= 0 && dnt < seconds)
            {
                seconds = dnt;
                next    = "dn";
            }

            double sec_fraction = seconds;
            int    s            = (int)Math.Round(sec_fraction);

            sec_fraction -= s;
            int minutes = s / 60;

            s -= minutes * 60;
            int hours = minutes / 60;

            minutes -= hours * 60;
            float width  = Resources.digits.width;
            float height = Resources.digits.height / 11;
            int   x      = minutes % 10;

            GUI.DrawTextureWithTexCoords(new Rect(150f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f));
            x = minutes / 10;
            GUI.DrawTextureWithTexCoords(new Rect(130f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits6, new Rect(0f, (float)(x * 0.143), 1f, 0.143f));
            x = hours % 10;
            GUI.DrawTextureWithTexCoords(new Rect(100f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f));
            x = hours / 10;
            x = x % 10;
            GUI.DrawTextureWithTexCoords(new Rect(80f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f));
            x = hours / 100;
            x = x % 10;
            GUI.DrawTextureWithTexCoords(new Rect(60f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(x * 0.091), 1f, 0.091f));
            //Seconds
            //109, 132
            double fx = s % 10 + sec_fraction;

            GUI.DrawTextureWithTexCoords(new Rect(198f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits, new Rect(0f, (float)(fx * 0.091), 1f, 0.091f));
            x = s / 10;
            GUI.DrawTextureWithTexCoords(new Rect(178f * Scale, 261f * Scale, width * Scale, height * Scale), Resources.digits6, new Rect(0f, (float)(x * 0.143), 1f, 0.143f));
        }
        /// <summary>
        ///     Updates the details by recalculating if requested.
        /// </summary>
        public void Update()
        {
            ITargetable    target = null;
            global::Vessel vessel = null;

            if (HighLogic.LoadedSceneIsFlight)
            {
                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;
                }
                else
                {
                    target = FlightGlobals.ActiveVessel.targetObject;
                    vessel = FlightGlobals.ActiveVessel;
                }
            }
            else if (HighLogic.LoadedScene == GameScenes.TRACKSTATION)
            {
                if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.CelestialBody)
                {
                    target = PlanetariumCamera.fetch.target.celestialBody;
                }
                else if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.Vessel)
                {
                    target = PlanetariumCamera.fetch.target.vessel;
                }

                if (TrackingStationSource != null)
                {
                    vessel = TrackingStationSource.GetVessel();
                }
                else
                {
                    TrackingStationSource = target;
                }
            }

            activeTarget = target;

            if (target == null)
            {
                ShowDetails = false;
                return;
            }

            ShowDetails = true;

            var actualSourceOrbit = vessel != null ? vessel.orbit : TrackingStationSource.GetOrbit();
            var actualTargetOrbit = target.GetOrbit();

            if (target is global::Vessel)
            {
                targetVessel = (global::Vessel)target;
            }
            else
            {
                targetVessel = null;
            }

            activeVessel = vessel;

            if (actualSourceOrbit == null)
            {
                //  Debug.Log("Source orbit is null!");
                TrackingStationSource = null;
                ShowDetails           = false;
                return;
            }

            if (actualTargetOrbit == null)
            {
                // Debug.Log("Target orbit is null!");
                ShowDetails = false;
                return;
            }

            isLanded = vessel != null && vessel.LandedOrSplashed;
            bool targetLanded = (target is global::Vessel && ((global::Vessel)target).LandedOrSplashed);

            landedSamePlanet = isLanded && targetLanded && actualSourceOrbit.referenceBody == actualTargetOrbit.referenceBody;

            var originOrbit = isLanded ? actualSourceOrbit.referenceBody.orbit : actualSourceOrbit;
            var targetOrbit = targetLanded ? actualTargetOrbit.referenceBody.orbit : actualTargetOrbit;

            if ((!isLanded && !targetLanded) || (actualSourceOrbit.referenceBody != actualTargetOrbit.referenceBody))
            {
                findConcentricParents(ref originOrbit, ref targetOrbit);
            }

            if (originOrbit == targetOrbit && !landedSamePlanet)
            {
                targetOrbit = actualTargetOrbit;
                originOrbit = null;
            }

            AltitudeSeaLevel    = targetOrbit.altitude;
            ApoapsisHeight      = targetOrbit.ApA;
            PeriapsisHeight     = targetOrbit.PeA;
            TimeToApoapsis      = targetOrbit.timeToAp;
            TimeToPeriapsis     = targetOrbit.timeToPe;
            SemiMajorAxis       = targetOrbit.semiMajorAxis;
            SemiMinorAxis       = targetOrbit.semiMinorAxis;
            OrbitalPeriod       = targetOrbit.period;
            RelativeInclination = targetOrbit.inclination;

            TimeToAscendingNode   = 0;
            TimeToDescendingNode  = 0;
            AngleToAscendingNode  = 0;
            AngleToDescendingNode = 0;

            RelativeVelocity    = 0;
            RelativeSpeed       = 0;
            PhaseAngle          = 0;
            InterceptAngle      = 0;
            TimeToTransferAngle = 0;

            AngleToPlane[0] = 0;
            TimeToPlane[0]  = 0;
            AngleToPlane[1] = 0;
            TimeToPlane[1]  = 0;
            Distance        = 0;

            if (originOrbit != null)
            {
                overrideANDN    = isLanded && actualSourceOrbit.referenceBody == targetOrbit.referenceBody;
                overrideANDNRev = targetLanded && !isLanded && actualTargetOrbit.referenceBody == actualSourceOrbit.referenceBody && target.GetVessel() != null;

                if (landedSamePlanet)   //this should only occur when landed targeting something else landed on same body.

                {
                    AltitudeSeaLevel = target.GetVessel().altitude;
                    ApoapsisHeight   = 0;
                    PeriapsisHeight  = 0;
                    TimeToApoapsis   = 0;
                    TimeToPeriapsis  = 0;
                    SemiMajorAxis    = 0;
                    SemiMinorAxis    = 0;

                    bodyRotationPeriod = actualSourceOrbit.referenceBody.rotationPeriod;

                    Distance = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D());

                    OrbitalPeriod = bodyRotationPeriod;

                    TimeToRendezvous       = 0;
                    RelativeRadialVelocity = 0;
                }
                else
                {
                    RelativeInclination = originOrbit.GetRelativeInclination(targetOrbit);
                    RelativeSpeed       = originOrbit.orbitalSpeed - targetOrbit.orbitalSpeed;
                    RelativeVelocity    = RelativeSpeed;
                    PhaseAngle          = originOrbit.GetPhaseAngle(targetOrbit);
                    InterceptAngle      = CalcInterceptAngle(targetOrbit, originOrbit);

                    double tspd = 360 / targetOrbit.period;
                    double sspd = 360 / originOrbit.period;


                    if (PhaseAngle < 0)
                    {
                        double diff = InterceptAngle - PhaseAngle;
                        if (diff < 0)
                        {
                            diff += 360;
                        }
                        if (diff > 340)
                        {
                            diff -= 360;
                        }
                        TimeToTransferAngle = sspd == tspd ? 0 : diff / (tspd - sspd);
                    }
                    else
                    {
                        double diff = PhaseAngle - InterceptAngle;
                        if (diff < 0)
                        {
                            diff += 360;
                        }
                        if (diff > 340)
                        {
                            diff -= 360;
                        }
                        TimeToTransferAngle = sspd == tspd ? 0 : diff / (sspd - tspd);
                    }


                    TimeToAscendingNode   = originOrbit.GetTimeToVector(GetAscendingNode(targetOrbit, originOrbit));
                    TimeToDescendingNode  = originOrbit.GetTimeToVector(GetDescendingNode(targetOrbit, originOrbit));
                    AngleToAscendingNode  = originOrbit.GetAngleToVector(GetAscendingNode(targetOrbit, originOrbit));
                    AngleToDescendingNode = originOrbit.GetAngleToVector(GetDescendingNode(targetOrbit, originOrbit));

                    Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos);

                    bodyRotationPeriod = actualSourceOrbit.referenceBody.rotationPeriod;

                    // beware that the order/sign of coordinates is inconsistent across different exposed variables
                    // in particular, v below does not equal to FlightGlobals.ship_tgtVelocity
                    Vector3d x  = targetOrbit.pos - originOrbit.pos;
                    Vector3d v  = targetOrbit.vel - originOrbit.vel;
                    double   xv = Vector3d.Dot(x, v);
                    TimeToRendezvous       = -xv / Vector3d.SqrMagnitude(v);
                    RelativeRadialVelocity = xv / Vector3d.Magnitude(x);

                    if (overrideANDN) //calc launch time
                    {
                        if (vessel != null)
                        {
                            AngleToPlane   = CalcAngleToPlane(vessel.GetOrbit().referenceBody, vessel.latitude, vessel.longitude, targetOrbit);
                            TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                            TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                        }

                        RelativeInclination    = targetOrbit.inclination;
                        RelativeRadialVelocity = 0;
                        TimeToRendezvous       = 0;
                        PhaseAngle             = 0;
                        InterceptAngle         = 0;
                        TimeToTransferAngle    = 0;
                    }
                    else if (overrideANDNRev)     //calc land time.
                    {
                        global::Vessel tgt = target.GetVessel();

                        if (vessel != null)
                        {
                            AngleToPlane   = CalcAngleToPlane(vessel.GetOrbit().referenceBody, tgt.latitude, tgt.longitude, originOrbit);
                            TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                            TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                        }

                        RelativeInclination    = originOrbit.inclination;
                        Distance               = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D());
                        AltitudeSeaLevel       = tgt.altitude;
                        PhaseAngle             = 0;
                        InterceptAngle         = 0;
                        TimeToTransferAngle    = 0;
                        ApoapsisHeight         = 0;
                        PeriapsisHeight        = 0;
                        TimeToApoapsis         = 0;
                        TimeToPeriapsis        = 0;
                        SemiMajorAxis          = 0;
                        SemiMinorAxis          = 0;
                        OrbitalPeriod          = 0;
                        RelativeRadialVelocity = 0;
                        TimeToRendezvous       = 0;
                    }
                }
            }

            if (actualTargetOrbit != targetOrbit)
            {
                targetDisplay = findNameForOrbit(targetOrbit, target);
            }
            else
            {
                targetDisplay = null;
            }

            if (originOrbit == null)
            {
                sourceDisplay = "N/A";
            }
            else if (actualSourceOrbit != originOrbit || HighLogic.LoadedScene == GameScenes.TRACKSTATION)
            {
                sourceDisplay = findNameForOrbit(originOrbit, vessel != null ? vessel : TrackingStationSource);
            }
            else
            {
                sourceDisplay = null;
            }
        }
Пример #19
0
        public static void Update()
        {
            _update = false;

            if (FlightGlobals.ActiveVessel == null ||
                FlightGlobals.ActiveVessel.targetObject == null ||
                FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null ||
                FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody == null ||
                FlightGlobals.ActiveVessel.orbit == null ||
                FlightGlobals.ActiveVessel.orbit.referenceBody == null)
            {
                _updated = false;
                return;
            }

            _updated = true;

            Orbit active = _activeVessel.orbit;
            Orbit target = _targetObject.GetOrbit();

            _trueShipOrbit = active;

            _showAngle   = false;
            _showPhasing = false;

            _shipOrbit   = null;
            _targetOrbit = null;

            if (active.referenceBody == target.referenceBody)
            {
                _shipOrbit   = active;
                _targetOrbit = target;
            }
            else
            {
                if (active.referenceBody == Planetarium.fetch.Sun)
                {
                    _shipOrbit   = active;
                    _targetOrbit = target;
                }
                else
                {
                    _showAngle = true;
                }

                _showPhasing = true;

                DrillDownOrbits(active, target);
            }

            Vessel.Situations sit = _activeVessel.situation;

            if ((sit |= Vessel.Situations.LANDED | Vessel.Situations.SPLASHED | Vessel.Situations.PRELAUNCH) == 0)
            {
                _vesselIntersect = false;
                _bodyIntersect   = false;
            }
            else
            {
                if (!_isVessel && !_isCelestial)
                {
                    _vesselIntersect = false;
                    _bodyIntersect   = false;
                }
                else
                {
                    OrbitTargeter      oTargeter = _activeVessel.orbitTargeter;
                    PatchedConicSolver solver    = _activeVessel.patchedConicSolver;

                    if (oTargeter == null || solver == null)
                    {
                        _vesselIntersect = false;
                        _bodyIntersect   = false;
                    }
                    else if (!MapView.MapIsEnabled)
                    {
                        if (_isVessel)
                        {
                            _bodyIntersect = false;

                            Vessel tgt = _targetObject.GetVessel();

                            if (tgt == null || tgt.LandedOrSplashed)
                            {
                                _vesselIntersect = false;
                                return;
                            }

                            Orbit _refPatch = null;

                            if (solver.maneuverNodes.Count > 0)
                            {
                                _refPatch = GetReferencePatch(oTargeter, solver, target.referenceBody, null, true);
                            }
                            else
                            {
                                _refPatch = BasicOrbitReflection.GetRefPatch(oTargeter);
                            }

                            Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter);

                            _vesselIntersect = GetClosestVessel(_refPatch, _tgtRefPatch);
                        }
                        else
                        {
                            _vesselIntersect = false;

                            double Pe = GetLowestPeA(solver);

                            if (Pe < BasicExtensions.AlmostMaxValue)
                            {
                                _closestDist   = Pe;
                                _bodyIntersect = true;
                            }
                            else
                            {
                                Orbit _refPatch = null;

                                if (solver.maneuverNodes.Count > 0)
                                {
                                    _refPatch = GetReferencePatch(oTargeter, solver, _targetBody, target.referenceBody, false);
                                }
                                else
                                {
                                    _refPatch = BasicOrbitReflection.GetRefPatch(oTargeter);
                                }

                                if (_refPatch != null && _refPatch.closestTgtApprUT <= 0)
                                {
                                    _bodyIntersect = false;
                                    return;
                                }

                                Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter);

                                _bodyIntersect = GetClosestCelestial(_refPatch, _tgtRefPatch);
                            }
                        }
                    }
                    else
                    {
                        if (_markers == null || _markers.Count <= 0)
                        {
                            _markers = BasicOrbitReflection.GetOrbitMarkers(oTargeter);
                        }

                        if (_markers == null || _markers.Count <= 0)
                        {
                            _vesselIntersect = false;
                            _bodyIntersect   = false;
                        }
                        else if (_isVessel)
                        {
                            _bodyIntersect = false;

                            if (solver.maneuverNodes.Count > 0)
                            {
                                Orbit _refPatch    = GetReferencePatch(oTargeter, solver, target.referenceBody, null, true);
                                Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter);

                                _vesselIntersect = GetClosestVessel(_refPatch, _tgtRefPatch);
                            }
                            else
                            {
                                OrbitTargeter.ISectMarker _intersectOne = null;
                                OrbitTargeter.ISectMarker _intersectTwo = null;

                                for (int i = _markers.Count - 1; i >= 0; i--)
                                {
                                    OrbitTargeter.Marker m = _markers[i];

                                    if (m == null)
                                    {
                                        continue;
                                    }

                                    if (!(m is OrbitTargeter.ISectMarker))
                                    {
                                        continue;
                                    }

                                    int num = ((OrbitTargeter.ISectMarker)m).num;

                                    if (num == 1)
                                    {
                                        _intersectOne = m as OrbitTargeter.ISectMarker;
                                    }
                                    else if (num == 2)
                                    {
                                        _intersectTwo = m as OrbitTargeter.ISectMarker;
                                    }
                                }

                                OrbitTargeter.ISectMarker _closestIntersect = null;

                                if (_intersectOne != null && _intersectTwo != null)
                                {
                                    _closestIntersect = _intersectOne.separation > _intersectTwo.separation ? _intersectTwo : _intersectOne;
                                }
                                else if (_intersectOne != null)
                                {
                                    _closestIntersect = _intersectOne;
                                }
                                else if (_intersectTwo != null)
                                {
                                    _closestIntersect = _intersectTwo;
                                }
                                else
                                {
                                    _closestIntersect = null;
                                }

                                if (_closestIntersect == null)
                                {
                                    _vesselIntersect = false;
                                }
                                else
                                {
                                    _vesselIntersect = true;
                                    _closestDist     = _closestIntersect.separation * 1000;
                                    _closestRelVel   = _closestIntersect.relSpeed;
                                    _closestTime     = _closestIntersect.UT;
                                }
                            }
                        }
                        else
                        {
                            _vesselIntersect = false;

                            double Pe = GetLowestPeA(solver);

                            if (Pe < BasicExtensions.AlmostMaxValue)
                            {
                                _closestDist   = Pe;
                                _bodyIntersect = true;
                            }
                            else
                            {
                                if (solver.maneuverNodes.Count > 0)
                                {
                                    Orbit _refPatch    = GetReferencePatch(oTargeter, solver, _targetBody, target.referenceBody, false);
                                    Orbit _tgtRefPatch = BasicOrbitReflection.GetTargetRefPatch(oTargeter);

                                    _bodyIntersect = GetClosestCelestial(_refPatch, _tgtRefPatch);
                                }
                                else
                                {
                                    OrbitTargeter.ClApprMarker _approach = null;

                                    for (int i = _markers.Count - 1; i >= 0; i--)
                                    {
                                        OrbitTargeter.Marker m = _markers[i];

                                        if (m == null)
                                        {
                                            continue;
                                        }

                                        if (!(m is OrbitTargeter.ClApprMarker))
                                        {
                                            continue;
                                        }

                                        _approach = m as OrbitTargeter.ClApprMarker;
                                    }

                                    if (_approach == null)
                                    {
                                        _bodyIntersect = false;
                                    }
                                    else
                                    {
                                        _bodyIntersect = true;
                                        _closestDist   = _approach.separation * 1000;
                                        _closestTime   = (_approach.dT * -1) + Planetarium.GetUniversalTime();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #20
0
        private void checkOrbit()
        {
            if (_manager.SelectedManeuverNode == null || _snapTab == null)
            {
                return;
            }

            if (_patch == null)
            {
                SetFields();
            }

            double UT = Planetarium.GetUniversalTime();

            //_snapTab.CurrentTime.OnTextUpdate.Invoke(string.Format("Maneuver Node #{0}: T {1}", _index + 1, KSPUtil.PrintTime(UT - _manager.SelectedManeuverNode.UT, 3, true)));
            _snapTab.ResetTime.OnTextUpdate.Invoke(string.Format("{0}", KSPUtil.PrintTime(_startUT - UT, 3, false)));

            if (_patch.eccentricity >= 1)
            {
                if (_manager.SelectedManeuverNode.attachedGizmo != null)
                {
                    _manager.SelectedManeuverNode.attachedGizmo.orbitsAdded = 0;
                }

                _orbitsAdded = 0;

                _snapTab.NextOrbitButton.gameObject.SetActive(false);
                _snapTab.PreviousOrbitButton.gameObject.SetActive(false);

                _snapTab.ApoButton.gameObject.SetActive(false);

                if (_patch.timeToPe < 0)
                {
                    _snapTab.PeriButton.gameObject.SetActive(false);
                }
                else if (_patch.PeR < 0)
                {
                    _snapTab.PeriButton.gameObject.SetActive(false);
                }
                else if (_patch.UTsoi > 0 && _patch.timeToPe + _patch.StartUT > _patch.UTsoi)
                {
                    _snapTab.PeriButton.gameObject.SetActive(false);
                }
                else
                {
                    _snapTab.PeriButton.gameObject.SetActive(true);
                    periUT = _patch.StartUT + _patch.timeToPe;
                }

                if ((_patch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE || _patch.patchEndTransition == Orbit.PatchTransitionType.MANEUVER) &&
                    (_patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE))
                {
                    _snapTab.NextPatchButton.gameObject.SetActive(true);

                    if (_patch.nextPatch.nextPatch.UTsoi > 0)
                    {
                        nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.UTsoi - _patch.nextPatch.nextPatch.StartUT) / 2);
                    }
                    else if (_patch.nextPatch.nextPatch.eccentricity < 1 && !double.IsNaN(_patch.nextPatch.nextPatch.period) && !double.IsInfinity(_patch.nextPatch.nextPatch.period))
                    {
                        nextPUT = _patch.nextPatch.nextPatch.StartUT + (_patch.nextPatch.nextPatch.period / 2);
                    }
                    else
                    {
                        nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.EndUT - _patch.nextPatch.nextPatch.StartUT) / 2);
                    }
                }
                else
                {
                    _snapTab.NextPatchButton.gameObject.SetActive(false);
                }

                if (_patch.patchStartTransition == Orbit.PatchTransitionType.INITIAL || _patch.patchStartTransition == Orbit.PatchTransitionType.MANEUVER)
                {
                    _snapTab.PreviousPatchButton.gameObject.SetActive(false);
                }
                else
                {
                    _snapTab.PreviousPatchButton.gameObject.SetActive(true);

                    if (_patch.previousPatch.UTsoi > 0)
                    {
                        prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.UTsoi - _patch.previousPatch.StartUT) / 2);
                    }
                    else if (_patch.previousPatch.eccentricity < 1 && !double.IsNaN(_patch.previousPatch.period) && !double.IsInfinity(_patch.previousPatch.period))
                    {
                        prevPUT = _patch.previousPatch.StartUT + (_patch.previousPatch.period / 2);
                    }
                    else
                    {
                        prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.EndUT - _patch.previousPatch.StartUT) / 2);
                    }
                }

                eqAscUT = ManeuverUtilities.EqAscTime(_patch);

                if (_patch.UTsoi > 0 && eqAscUT > _patch.UTsoi)
                {
                    _snapTab.EqAscButton.gameObject.SetActive(false);
                }
                else if (eqAscUT < UT)
                {
                    _snapTab.EqAscButton.gameObject.SetActive(false);
                }
                else
                {
                    _snapTab.EqAscButton.gameObject.SetActive(true);
                }

                eqDescUT = ManeuverUtilities.EqDescTime(_patch);

                if (_patch.UTsoi > 0 && eqDescUT > _patch.UTsoi)
                {
                    _snapTab.EqDescButton.gameObject.SetActive(false);
                }
                else if (eqDescUT < UT)
                {
                    _snapTab.EqDescButton.gameObject.SetActive(false);
                }
                else
                {
                    _snapTab.EqDescButton.gameObject.SetActive(true);
                }

                ITargetable target = FlightGlobals.fetch.VesselTarget;

                if (target == null)
                {
                    _snapTab.RelAscButton.gameObject.SetActive(false);
                    _snapTab.RelDescButton.gameObject.SetActive(false);
                    _snapTab.ClAppButton.gameObject.SetActive(false);
                }
                else
                {
                    Orbit tgtPatch = target.GetOrbit();

                    if (tgtPatch.referenceBody != _patch.referenceBody)
                    {
                        _snapTab.RelAscButton.gameObject.SetActive(false);
                        _snapTab.RelDescButton.gameObject.SetActive(false);
                        _snapTab.ClAppButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        relAscUT = ManeuverUtilities.RelAscTime(_patch, target);

                        if (_patch.UTsoi > 0 && relAscUT > _patch.UTsoi)
                        {
                            _snapTab.RelAscButton.gameObject.SetActive(false);
                        }
                        else if (relAscUT < UT)
                        {
                            _snapTab.RelAscButton.gameObject.SetActive(false);
                        }
                        else
                        {
                            _snapTab.RelAscButton.gameObject.SetActive(true);
                        }

                        relDescUT = ManeuverUtilities.RelDescTime(_patch, target);

                        if (_patch.UTsoi > 0 && relDescUT > _patch.UTsoi)
                        {
                            _snapTab.RelDescButton.gameObject.SetActive(false);
                        }
                        else if (relDescUT < UT)
                        {
                            _snapTab.RelDescButton.gameObject.SetActive(false);
                        }
                        else
                        {
                            _snapTab.RelDescButton.gameObject.SetActive(true);
                        }

                        if (target.GetVessel() == null)
                        {
                            clAppUT = _patch.closestTgtApprUT;
                        }
                        else
                        {
                            clAppUT = ManeuverUtilities.closestVessel(0, _patch, tgtPatch, true, 0, 0);
                        }

                        if (clAppUT <= 0)
                        {
                            _snapTab.ClAppButton.gameObject.SetActive(false);
                        }
                        else if (_patch.UTsoi > 0 && clAppUT > _patch.UTsoi)
                        {
                            _snapTab.ClAppButton.gameObject.SetActive(false);
                        }
                        else if (clAppUT < UT)
                        {
                            _snapTab.ClAppButton.gameObject.SetActive(false);
                        }
                        else
                        {
                            _snapTab.ClAppButton.gameObject.SetActive(true);
                        }
                    }
                }
            }
            else
            {
                if (_patch.patchEndTransition == Orbit.PatchTransitionType.FINAL)
                {
                    if (!double.IsNaN(_patch.period) && !double.IsInfinity(_patch.period))
                    {
                        _snapTab.NextOrbitButton.gameObject.SetActive(true);
                        nextOUT = _manager.SelectedManeuverNode.UT + _patch.period;
                    }
                    else
                    {
                        _snapTab.NextOrbitButton.gameObject.SetActive(false);
                    }

                    if (double.IsNaN(_patch.period) || double.IsInfinity(_patch.period) || _manager.SelectedManeuverNode.UT - _patch.period < UT)
                    {
                        _snapTab.PreviousOrbitButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        _snapTab.PreviousOrbitButton.gameObject.SetActive(true);
                        prevOUT = _manager.SelectedManeuverNode.UT - _patch.period;
                    }

                    _snapTab.ApoButton.gameObject.SetActive(true);
                    apoUT = _patch.StartUT + _patch.timeToAp;

                    _snapTab.PeriButton.gameObject.SetActive(true);
                    periUT = _patch.StartUT + _patch.timeToPe;

                    _snapTab.NextPatchButton.gameObject.SetActive(false);

                    if (_patch.patchStartTransition == Orbit.PatchTransitionType.INITIAL || _patch.patchStartTransition == Orbit.PatchTransitionType.MANEUVER)
                    {
                        _snapTab.PreviousPatchButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        _snapTab.PreviousPatchButton.gameObject.SetActive(true);

                        if (_patch.previousPatch.UTsoi > 0)
                        {
                            prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.UTsoi - _patch.previousPatch.StartUT) / 2);
                        }
                        else if (_patch.previousPatch.eccentricity < 1 && !double.IsNaN(_patch.previousPatch.period) && !double.IsInfinity(_patch.previousPatch.period))
                        {
                            prevPUT = _patch.previousPatch.StartUT + (_patch.previousPatch.period / 2);
                        }
                        else
                        {
                            prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.EndUT - _patch.previousPatch.StartUT) / 2);
                        }
                    }

                    _snapTab.EqAscButton.gameObject.SetActive(true);
                    eqAscUT = ManeuverUtilities.EqAscTime(_patch);

                    _snapTab.EqDescButton.gameObject.SetActive(true);
                    eqDescUT = ManeuverUtilities.EqDescTime(_patch);

                    ITargetable target = FlightGlobals.fetch.VesselTarget;

                    if (target == null)
                    {
                        _snapTab.RelAscButton.gameObject.SetActive(false);
                        _snapTab.RelDescButton.gameObject.SetActive(false);
                        _snapTab.ClAppButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        Orbit tgtPatch = target.GetOrbit();

                        if (tgtPatch.referenceBody != _patch.referenceBody)
                        {
                            _snapTab.RelAscButton.gameObject.SetActive(false);
                            _snapTab.RelDescButton.gameObject.SetActive(false);
                            _snapTab.ClAppButton.gameObject.SetActive(false);
                        }
                        else
                        {
                            _snapTab.RelAscButton.gameObject.SetActive(true);
                            relAscUT = ManeuverUtilities.RelAscTime(_patch, target);

                            _snapTab.RelDescButton.gameObject.SetActive(true);
                            relDescUT = ManeuverUtilities.RelDescTime(_patch, target);

                            if (target.GetVessel() == null)
                            {
                                clAppUT = _patch.closestTgtApprUT;
                            }
                            else
                            {
                                clAppUT = ManeuverUtilities.closestVessel(0, _patch, tgtPatch, true, 0, 0);
                            }

                            if (clAppUT <= 0)
                            {
                                _snapTab.ClAppButton.gameObject.SetActive(false);
                            }
                            else
                            {
                                _snapTab.ClAppButton.gameObject.SetActive(true);
                            }
                        }
                    }
                }
                else
                {
                    if (_manager.SelectedManeuverNode.attachedGizmo != null)
                    {
                        _manager.SelectedManeuverNode.attachedGizmo.orbitsAdded = 0;
                    }

                    _orbitsAdded = 0;

                    _snapTab.NextOrbitButton.gameObject.SetActive(false);
                    _snapTab.PreviousOrbitButton.gameObject.SetActive(false);

                    if (_patch.timeToAp < 0)
                    {
                        _snapTab.ApoButton.gameObject.SetActive(false);
                    }
                    if (_patch.UTsoi > 0 && _patch.timeToAp + _patch.StartUT > _patch.UTsoi)
                    {
                        _snapTab.ApoButton.gameObject.SetActive(false);
                    }
                    if (_patch.ApA > _patch.referenceBody.sphereOfInfluence)
                    {
                        _snapTab.ApoButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        _snapTab.ApoButton.gameObject.SetActive(true);
                        apoUT = _patch.StartUT + _patch.timeToAp;
                    }

                    if (_patch.timeToPe < 0)
                    {
                        _snapTab.PeriButton.gameObject.SetActive(false);
                    }
                    else if (_patch.PeR < 0)
                    {
                        _snapTab.PeriButton.gameObject.SetActive(false);
                    }
                    else if (_patch.UTsoi > 0 && _patch.timeToPe + _patch.StartUT > _patch.UTsoi)
                    {
                        _snapTab.PeriButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        _snapTab.PeriButton.gameObject.SetActive(true);
                        periUT = _patch.StartUT + _patch.timeToPe;
                    }

                    if ((_patch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE || _patch.patchEndTransition == Orbit.PatchTransitionType.MANEUVER) &&
                        (_patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER || _patch.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE))
                    {
                        _snapTab.NextPatchButton.gameObject.SetActive(true);

                        if (_patch.nextPatch.nextPatch.UTsoi > 0)
                        {
                            nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.UTsoi - _patch.nextPatch.nextPatch.StartUT) / 2);
                        }
                        else if (_patch.nextPatch.nextPatch.eccentricity < 1 && !double.IsNaN(_patch.nextPatch.nextPatch.period) && !double.IsInfinity(_patch.nextPatch.nextPatch.period))
                        {
                            nextPUT = _patch.nextPatch.nextPatch.StartUT + (_patch.nextPatch.nextPatch.period / 2);
                        }
                        else
                        {
                            nextPUT = _patch.nextPatch.nextPatch.StartUT + ((_patch.nextPatch.nextPatch.EndUT - _patch.nextPatch.nextPatch.StartUT) / 2);
                        }
                    }
                    else
                    {
                        _snapTab.NextPatchButton.gameObject.SetActive(false);
                    }

                    if (_patch.patchStartTransition == Orbit.PatchTransitionType.INITIAL || _patch.patchStartTransition == Orbit.PatchTransitionType.MANEUVER)
                    {
                        _snapTab.PreviousPatchButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        _snapTab.PreviousPatchButton.gameObject.SetActive(true);

                        if (_patch.previousPatch.UTsoi > 0)
                        {
                            prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.UTsoi - _patch.previousPatch.StartUT) / 2);
                        }
                        else if (_patch.previousPatch.eccentricity < 1 && !double.IsNaN(_patch.previousPatch.period) && !double.IsInfinity(_patch.previousPatch.period))
                        {
                            prevPUT = _patch.previousPatch.StartUT + (_patch.previousPatch.period / 2);
                        }
                        else
                        {
                            prevPUT = _patch.previousPatch.StartUT + ((_patch.previousPatch.EndUT - _patch.previousPatch.StartUT) / 2);
                        }
                    }

                    eqAscUT = ManeuverUtilities.EqAscTime(_patch);

                    if (_patch.UTsoi > 0 && eqAscUT > _patch.UTsoi)
                    {
                        _snapTab.EqAscButton.gameObject.SetActive(false);
                    }
                    else if (eqAscUT < UT)
                    {
                        _snapTab.EqAscButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        _snapTab.EqAscButton.gameObject.SetActive(true);
                    }

                    eqDescUT = ManeuverUtilities.EqDescTime(_patch);

                    if (_patch.UTsoi > 0 && eqDescUT > _patch.UTsoi)
                    {
                        _snapTab.EqDescButton.gameObject.SetActive(false);
                    }
                    else if (eqDescUT < UT)
                    {
                        _snapTab.EqDescButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        _snapTab.EqDescButton.gameObject.SetActive(true);
                    }

                    ITargetable target = FlightGlobals.fetch.VesselTarget;

                    if (target == null)
                    {
                        _snapTab.RelAscButton.gameObject.SetActive(false);
                        _snapTab.RelDescButton.gameObject.SetActive(false);
                        _snapTab.ClAppButton.gameObject.SetActive(false);
                    }
                    else
                    {
                        Orbit tgtPatch = target.GetOrbit();

                        if (tgtPatch.referenceBody != _patch.referenceBody)
                        {
                            _snapTab.RelAscButton.gameObject.SetActive(false);
                            _snapTab.RelDescButton.gameObject.SetActive(false);
                            _snapTab.ClAppButton.gameObject.SetActive(false);
                        }
                        else
                        {
                            relAscUT = ManeuverUtilities.RelAscTime(_patch, target);

                            if (_patch.UTsoi > 0 && relAscUT > _patch.UTsoi)
                            {
                                _snapTab.RelAscButton.gameObject.SetActive(false);
                            }
                            else if (relAscUT < UT)
                            {
                                _snapTab.RelAscButton.gameObject.SetActive(false);
                            }
                            else
                            {
                                _snapTab.RelAscButton.gameObject.SetActive(true);
                            }

                            relDescUT = ManeuverUtilities.RelDescTime(_patch, target);

                            if (_patch.UTsoi > 0 && relDescUT > _patch.UTsoi)
                            {
                                _snapTab.RelDescButton.gameObject.SetActive(false);
                            }
                            else if (relDescUT < UT)
                            {
                                _snapTab.RelDescButton.gameObject.SetActive(false);
                            }
                            else
                            {
                                _snapTab.RelDescButton.gameObject.SetActive(true);
                            }

                            if (target.GetVessel() == null)
                            {
                                clAppUT = _patch.closestTgtApprUT;
                            }
                            else
                            {
                                clAppUT = ManeuverUtilities.closestVessel(0, _patch, tgtPatch, true, 0, 0);
                            }

                            if (clAppUT <= 0)
                            {
                                _snapTab.ClAppButton.gameObject.SetActive(false);
                            }
                            else if (_patch.UTsoi > 0 && clAppUT > _patch.UTsoi)
                            {
                                _snapTab.ClAppButton.gameObject.SetActive(false);
                            }
                            else if (clAppUT < UT)
                            {
                                _snapTab.ClAppButton.gameObject.SetActive(false);
                            }
                            else
                            {
                                _snapTab.ClAppButton.gameObject.SetActive(true);
                            }
                        }
                    }
                }
            }
        }
        private void WindowLayout_AddPane_TargetDistance()
        {
            intAddDistanceHeight = 272;
            GUILayout.BeginVertical();
            GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading);

            //What are the possible targets??
            List<ITargetable> iTargets = new List<ITargetable>();
            if (!(KACWorkerGameState.CurrentVesselTarget == null))
            {
                iTargets.Add(KACWorkerGameState.CurrentVesselTarget);   //VesselTarget
            }
            iTargets.Add(KACWorkerGameState.CurrentVessel.mainBody);    //Body we are orbiting
            if (KACWorkerGameState.SOIPointExists)
            {
                iTargets.Add(KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody);   //Body we will orbit next
            }

            if (intSelectediTarget > iTargets.Count - 1)
                intSelectediTarget = 0;

            intAddDistanceHeight += (iTargets.Count*30);

            //Now give the user the choice
            GUILayout.BeginHorizontal();
            GUILayout.Label("Select Target:",KACResources.styleAddXferName);
            if (DrawRadioListVertical(ref intSelectediTarget, iTargets.Select(x => x.GetName()).ToArray()))
            {
                DebugLogFormatted("Distance Target is:{0}", iTargets[intSelectediTarget].GetName());
            }
            GUILayout.EndHorizontal();

            //Set the tgt Object
            tgtSelectedDistance=iTargets[intSelectediTarget];
            string strDistanceName = "Distance";
            if (tgtSelectedDistance is CelestialBody) strDistanceName = "Altitude";

            //Ask for the target distance/altitude
            GUILayout.BeginHorizontal();
            GUILayout.Label(string.Format("Target {0} (m):",strDistanceName), KACResources.styleAddXferName);
            dblTargetDistance= Convert.ToInt32(GUILayout.TextField(dblTargetDistance.ToString(),KACResources.styleAddField));
            GUILayout.EndHorizontal();

            //If the body has an atmosphere then add an option to set the Altitude straight to that
            if (tgtSelectedDistance is CelestialBody)
            {
                if ((tgtSelectedDistance as CelestialBody).atmosphere)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(string.Format("Atmosphere: {0}", (tgtSelectedDistance as CelestialBody).maxAtmosphereAltitude));
                    if (GUILayout.Button("Set to Edge"))
                    {
                        dblTargetDistance = (tgtSelectedDistance as CelestialBody).maxAtmosphereAltitude;
                    }
                    GUILayout.EndHorizontal();
                    intAddDistanceHeight += 26;
                }
            }

            //For a vessel give some options for orbits to look forwards
            GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
            if (!(tgtSelectedDistance is CelestialBody))
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label("Orbits to Search:", KACResources.styleAddHeading, GUILayout.Width(110));
                GUILayout.Label(((int)Math.Round((Decimal)fltOrbits_Distance, 0)).ToString(), KACResources.styleAddXferName, GUILayout.Width(25));
                fltOrbits_Distance = GUILayout.HorizontalSlider(fltOrbits_Distance, 1, 20);
                fltOrbits_Distance = (float)Math.Floor((Decimal)fltOrbits_Distance);
                GUILayout.EndHorizontal();
                intAddDistanceHeight += 18;
            }

            //What VesselOrbit do we care about
            Orbit VesselOrbitToCompare=KACWorkerGameState.CurrentVessel.GetOrbit();
            if ((KACWorkerGameState.SOIPointExists) && ((tgtSelectedDistance as CelestialBody) == KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody))
            {
                VesselOrbitToCompare = KACWorkerGameState.CurrentVessel.orbit.nextPatch;
            }
            //Get the startUT of the orbit
            Double VesselOrbitStartUT = KACWorkerGameState.CurrentVessel.GetOrbit().StartUT;

            //Set up some variables
            intOrbits_Distance = (int)fltOrbits_Distance;
            int intDistanceOrbitPass = 0;
            double dblClosestDistance = Double.MaxValue;
            double dblDistanceUT = 0;

            double dblOrbitTestDistance = Double.MaxValue;
            double dblOrbitTestDistanceUT = 0;

            //If its an Altitude alarm then do this
            if (tgtSelectedDistance is CelestialBody)
            {
                dblOrbitTestDistanceUT = KACUtils.timeOfTargetAltitude(VesselOrbitToCompare,
                                            VesselOrbitStartUT,
                                            out dblOrbitTestDistance,
                                            dblTargetDistance
                                            );

                dblClosestDistance = dblOrbitTestDistance;
                dblDistanceUT = dblOrbitTestDistanceUT;
            }
            else
            {
                //Else Iterate through the orbits to find the target separation
                for (int intOrbitToTest = 1; intOrbitToTest <= intOrbits_Distance; intOrbitToTest++)
                {
                    dblOrbitTestDistanceUT = KACUtils.timeOfTargetDistance(VesselOrbitToCompare,
                                                                tgtSelectedDistance.GetOrbit(),
                                                                KACWorkerGameState.CurrentTime.UT,
                                                                intOrbitToTest,
                                                                out dblOrbitTestDistance,
                                                                dblTargetDistance
                                                                );

                    if (dblOrbitTestDistance < dblClosestDistance)
                    {
                        dblClosestDistance = dblOrbitTestDistance;
                        dblDistanceUT = dblOrbitTestDistanceUT;
                        intDistanceOrbitPass = intOrbitToTest;
                    }
                }
            }

            //Now display what we got
            GUILayout.BeginHorizontal();
            GUILayout.Label(String.Format("{0}:",strDistanceName), KACResources.styleAddHeading, GUILayout.Width(70));
            String strDistance = string.Format("{0:#}m", dblClosestDistance);
            if (dblClosestDistance > 999) strDistance = string.Format("{0:#.0}km", dblClosestDistance / 1000);
            GUILayout.Label(strDistance, KACResources.styleAddXferName, GUILayout.Width(90));
            if (!(tgtSelectedDistance is CelestialBody))
            {
                GUILayout.Label("On Orbit:", KACResources.styleAddHeading);
                GUILayout.Label(intDistanceOrbitPass.ToString(), KACResources.styleAddXferName);
            }
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();

            //Now do the stuff to draw the alarm button
            String strMarginConversion = "";
            KACTime eventTime = new KACTime(dblDistanceUT);
            KACTime eventInterval = new KACTime(dblDistanceUT - KACWorkerGameState.CurrentTime.UT);

            KACTime eventAlarm;
            KACTime eventAlarmInterval;
            try
            {
                eventAlarm = new KACTime(eventTime.UT - timeMargin.UT);
                eventAlarmInterval = new KACTime(eventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT);
            }
            catch (Exception)
            {
                eventAlarm = null;
                eventAlarmInterval = null;
                strMarginConversion = "Unable to Add the Margin Minutes";
            }

            if ((eventTime.UT > KACWorkerGameState.CurrentTime.UT) && strMarginConversion == "")
            {
                if (DrawAddAlarm(eventTime, eventInterval, eventAlarmInterval))
                {
                    KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), strAlarmName, strAlarmNotes,
                        eventAlarm.UT, timeMargin.UT, AddType,
                        (AddAction == KACAlarm.AlarmAction.KillWarp), (AddAction == KACAlarm.AlarmAction.PauseGame));
                    newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget;
                    newAlarm.ManNodes = KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes;

                    Settings.Alarms.Add(newAlarm);
                    Settings.Save();
                    _ShowAddPane = false;
                }
            }
            else
            {
                strMarginConversion = "No Target Distance Approach found";
            }

            if (strMarginConversion != "")
                GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true));

            GUILayout.EndVertical();
        }
        private void FetchCommonData()
        {
            localGeeASL = vessel.orbit.referenceBody.GeeASL * gee;
            coM = vessel.findWorldCenterOfMass();
            localGeeDirect = FlightGlobals.getGeeForceAtPosition(coM).magnitude;
            up = (coM - vessel.mainBody.position).normalized;
            forward = vessel.GetTransform().up;
            right = vessel.GetTransform().right;
            north = Vector3d.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - coM).normalized;
            rotationSurface = Quaternion.LookRotation(north, up);
            rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface);

            velocityVesselOrbit = vessel.orbit.GetVel();
            velocityVesselSurface = velocityVesselOrbit - vessel.mainBody.getRFrmVel(coM);

            speedVertical = Vector3d.Dot(velocityVesselSurface, up);
            speedVerticalRounded = Math.Ceiling(speedVertical * 20) / 20;
            target = FlightGlobals.fetch.VesselTarget;
            node = vessel.patchedConicSolver.maneuverNodes.Count > 0 ? vessel.patchedConicSolver.maneuverNodes[0] : null;
            time = Planetarium.GetUniversalTime();
            FetchAltitudes();
            terrainHeight = altitudeASL - altitudeTrue;
            if (time >= lastTimePerSecond + 1) {
                terrainDelta = terrainHeight - lastTerrainHeight;
                lastTerrainHeight = terrainHeight;
                lastTimePerSecond = time;
            }

            horzVelocity = (velocityVesselSurface - (speedVertical * up)).magnitude;
            horzVelocityForward = Vector3d.Dot(velocityVesselSurface, forward);
            horzVelocityRight = Vector3d.Dot(velocityVesselSurface, right);

            atmPressure = FlightGlobals.getStaticPressure(altitudeASL, vessel.mainBody);
            dynamicPressure = 0.5 * velocityVesselSurface.sqrMagnitude * vessel.atmDensity;

            if (target != null) {
                targetSeparation = vessel.GetTransform().position - target.GetTransform().position;
                targetOrientation = target.GetTransform().rotation;

                targetVessel = target as Vessel;
                targetBody = target as CelestialBody;
                targetDockingNode = target as ModuleDockingNode;

                targetDistance = Vector3.Distance(target.GetTransform().position, vessel.GetTransform().position);

                // This is kind of messy.
                targetOrbitSensibility = false;
                // All celestial bodies except the sun have orbits that make sense.
                targetOrbitSensibility |= targetBody != null && targetBody != Planetarium.fetch.Sun;

                if (targetVessel != null)
                    targetOrbitSensibility = JUtil.OrbitMakesSense(targetVessel);
                if (targetDockingNode != null)
                    targetOrbitSensibility = JUtil.OrbitMakesSense(target.GetVessel());

                if (targetOrbitSensibility)
                    targetOrbit = target.GetOrbit();

                // TODO: Actually, there's a lot of nonsensical cases here that need more reasonable handling.
                // Like what if we're targeting a vessel landed on a moon of another planet?...
                if (targetOrbit != null) {
                    velocityRelativeTarget = vessel.orbit.GetVel() - target.GetOrbit().GetVel();
                } else {
                    velocityRelativeTarget = vessel.orbit.GetVel();
                }

                // If our target is somehow our own celestial body, approach speed is equal to vertical speed.
                if (targetBody == vessel.mainBody)
                    approachSpeed = speedVertical;
                // In all other cases, that should work. I think.
                approachSpeed = Vector3d.Dot(velocityRelativeTarget, (target.GetTransform().position - vessel.GetTransform().position).normalized);
            } else {
                velocityRelativeTarget = targetSeparation = Vector3d.zero;
                targetOrbit = null;
                targetDistance = 0;
                approachSpeed = 0;
                targetBody = null;
                targetVessel = null;
                targetDockingNode = null;
                targetOrientation = vessel.GetTransform().rotation;
                targetOrbitSensibility = false;
            }
            orbitSensibility = JUtil.OrbitMakesSense(vessel);
            if (vessel.situation == Vessel.Situations.SUB_ORBITAL || vessel.situation == Vessel.Situations.FLYING) {
                // Mental note: the local g taken from vessel.mainBody.GeeASL will suffice.
                //  t = (v+sqrt(v²+2gd))/g or something.

                // What is the vertical component of current acceleration?
                double accelUp = Vector3d.Dot(vessel.acceleration, up);

                double altitude = altitudeTrue;
                if (vessel.mainBody.ocean && altitudeASL > 0.0) {
                    // AltitudeTrue shows distance above the floor of the ocean,
                    // so use ASL if it's closer in this case, and we're not
                    // already below SL.
                    altitude = Math.Min(altitudeASL, altitudeTrue);
                }

                if (accelUp < 0.0 || speedVertical >= 0.0 || Planetarium.TimeScale > 1.0) {
                    // If accelUp is negative, we can't use it in the general
                    // equation for finding time to impact, since it could
                    // make the term inside the sqrt go negative.
                    // If we're going up, we can use this as well, since
                    // the precision is not critical.
                    // If we are warping, accelUp is always zero, so if we
                    // do not use this case, we would fall to the simple
                    // formula, which is wrong.
                    secondsToImpact = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * localGeeASL * altitude)) / localGeeASL;
                } else if (accelUp > 0.005) {
                    // This general case takes into account vessel acceleration,
                    // so estimates on craft that include parachutes or do
                    // powered descents are more accurate.
                    secondsToImpact = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * accelUp * altitude)) / accelUp;
                } else {
                    // If accelUp is small, we get floating point precision
                    // errors that tend to make secondsToImpact get really big.
                    secondsToImpact = altitude / -speedVertical;
                }

                // MOARdV: I think this gets the computation right.  High thrust will
                // result in NaN, which is already handled.
                /*
                double accelerationAtMaxThrust = localG - (totalMaximumThrust / totalShipWetMass);
                double timeToImpactAtMaxThrust = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * accelerationAtMaxThrust * altitude)) / accelerationAtMaxThrust;
                bestPossibleSpeedAtImpact = speedVertical - accelerationAtMaxThrust * timeToImpactAtMaxThrust;
                if (double.IsNaN(bestPossibleSpeedAtImpact))
                    bestPossibleSpeedAtImpact = 0;
                */
                bestPossibleSpeedAtImpact = SpeedAtImpact(totalMaximumThrust, totalShipWetMass, localGeeASL, speedVertical, altitude);
                expectedSpeedAtImpact = SpeedAtImpact(totalCurrentThrust, totalShipWetMass, localGeeASL, speedVertical, altitude);

            } else {
                secondsToImpact = Double.NaN;
                bestPossibleSpeedAtImpact = 0;
                expectedSpeedAtImpact = 0;
            }
        }
Пример #23
0
        public static void Add(Kerbulator kalc)
        {
            // Planets
            foreach (CelestialBody b in FlightGlobals.Bodies)
            {
                if (b.name == "Sun")
                {
                    AddCelestialBody(kalc, b, "Kerbol");
                }
                else
                {
                    AddCelestialBody(kalc, b, b.name);
                }
            }

            Vessel v      = FlightGlobals.ActiveVessel;
            Orbit  orbit1 = v.orbit;

            if (v != null)
            {
                // Current orbit
                AddOrbit(kalc, orbit1, "Craft");

                // Current position in carthesian coordinates
                AddVector3d(kalc, "Craft.Pos", v.GetWorldPos3D());

                // Navball (thank you MechJeb source)
                Vector3d   CoM                   = v.findWorldCenterOfMass();
                Vector3d   up                    = (CoM - v.mainBody.position).normalized;
                Vector3d   north                 = Vector3d.Exclude(up, (v.mainBody.position + v.mainBody.transform.up * (float)v.mainBody.Radius) - CoM).normalized;
                Quaternion rotationSurface       = Quaternion.LookRotation(north, up);
                Quaternion rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(v.GetTransform().rotation) * rotationSurface);
                Vector3d   velocityVesselOrbit   = v.orbit.GetVel();
                Vector3d   velocityVesselSurface = velocityVesselOrbit - v.mainBody.getRFrmVel(CoM);

                AddDouble(kalc, "Navball.Heading", rotationVesselSurface.eulerAngles.y);
                AddDouble(kalc, "Navball.Pitch", (rotationVesselSurface.eulerAngles.x > 180) ? (360.0 - rotationVesselSurface.eulerAngles.x) : -rotationVesselSurface.eulerAngles.x);
                AddDouble(kalc, "Navball.Roll", (rotationVesselSurface.eulerAngles.z > 180) ? (rotationVesselSurface.eulerAngles.z - 360.0) : rotationVesselSurface.eulerAngles.z);
                AddDouble(kalc, "Navball.OrbitalVelocity", velocityVesselOrbit.magnitude);
                AddDouble(kalc, "Navball.SurfaceVelocity", velocityVesselSurface.magnitude);
                AddDouble(kalc, "Navball.VerticalVelocity", Vector3d.Dot(velocityVesselSurface, up));

                // Current time
                double UT = (double)Planetarium.GetUniversalTime();
                AddDouble(kalc, "UT", UT);

                // Reference body
                AddCelestialBody(kalc, v.orbit.referenceBody, "Parent");

                // Target
                if (FlightGlobals.fetch.VesselTarget != null)
                {
                    ITargetable target = FlightGlobals.fetch.VesselTarget;
                    Orbit       orbit2 = target.GetOrbit();

                    // Target Orbit
                    AddOrbit(kalc, orbit2, "Target");

                    // Intersection with target orbit
                    double CD             = 0.0;
                    double CCD            = 0.0;
                    double FFp            = 0.0;
                    double FFs            = 0.0;
                    double SFp            = 0.0;
                    double SFs            = 0.0;
                    int    iterationCount = 0;
                    Orbit.FindClosestPoints(orbit1, orbit2, ref CD, ref CCD, ref FFp, ref FFs, ref SFp, ref SFs, 0.0, 100, ref iterationCount);
                    double T1 = orbit1.GetDTforTrueAnomaly(FFp, 0.0);
                    double T2 = orbit1.GetDTforTrueAnomaly(SFp, 0.0);
                    AddDouble(kalc, "Craft.Inter1.dt", T1);
                    AddDouble(kalc, "Craft.Inter1.Δt", T1);
                    AddDouble(kalc, "Craft.Inter1.Sep", (orbit1.getPositionAtUT(T1 + UT) - orbit2.getPositionAtUT(T1 + UT)).magnitude);
                    AddDouble(kalc, "Craft.Inter1.TrueAnomaly", orbit1.TrueAnomalyAtUT(T1 + UT));
                    AddDouble(kalc, "Craft.Inter1.θ", orbit1.TrueAnomalyAtUT(T1 + UT));
                    AddDouble(kalc, "Craft.Inter2.dt", T2);
                    AddDouble(kalc, "Craft.Inter2.Δt", T2);
                    AddDouble(kalc, "Craft.Inter2.Sep", (orbit1.getPositionAtUT(T2 + UT) - orbit2.getPositionAtUT(T2 + UT)).magnitude);
                    AddDouble(kalc, "Craft.Inter2.TrueAnomaly", orbit2.TrueAnomalyAtUT(T2 + UT));
                    AddDouble(kalc, "Craft.Inter2.θ", orbit2.TrueAnomalyAtUT(T2 + UT));
                }
            }
        }
 public Orbit GetOrbit()
 {
     return(target == null? null : target.GetOrbit());
 }
Пример #25
0
        private void CreateTransfers(ITargetable start)
        {
            DbgFmt("Fabricating transfers around {0}", TheName(start));

            if (hyperbolicOrbit && inbound)
            {
                // Just try to calculate a capture burn
                DbgFmt("Orbit is hyperbolic, creating transfer for capture");
                transfers.Add(new TransferModel(origin, origin.GetOrbit().referenceBody));
            }
            else
            {
                // Normal orbit, load up everything
                bool foundTarget = false;

                CelestialBody targetBody = FlightGlobals.fetch.VesselTarget as CelestialBody,
                              first      = start as CelestialBody;
                // If the starting point is a vessel or has no solid surface, then we can't
                // launch from it.
                if (first == null || !first.hasSolidSurface)
                {
                    first = start.GetOrbit()?.referenceBody;
                }

                for (CelestialBody b = first, toSkip = start as CelestialBody;
                     b != null;
                     toSkip = b, b = ParentBody(b))
                {
                    DbgFmt("Checking transfers around {0}", TheName(b));

                    // It's worth calculating return-from-satellite burns for Eve, Kerbin, and Duna,
                    // but not for Jool or the Sun.
                    if (b.hasSolidSurface && b != first)
                    {
                        DbgFmt("Adding return-to-parent transfer to {0}", TheName(b));
                        transfers.Add(new TransferModel(origin, b));
                    }

                    int numBodies = b.orbitingBodies.Count;
                    for (int i = 0; i < numBodies; ++i)
                    {
                        CelestialBody satellite = b.orbitingBodies[i];
                        if (satellite != toSkip)
                        {
                            DbgFmt("Allocating transfer to {0}", TheName(satellite));
                            transfers.Add(new TransferModel(origin, satellite));

                            if (satellite == targetBody)
                            {
                                DbgFmt("Found target as satellite");
                                foundTarget = true;
                            }
                        }
                    }

                    if (Settings.Instance.ShowTrackedAsteroids)
                    {
                        // Add any tracked asteroids in this SOI.
                        // Insertion sort into bodies according to semiMajorAxis.
                        for (int i = 0; i < FlightGlobals.Vessels.Count; ++i)
                        {
                            Vessel v = FlightGlobals.Vessels[i];

                            if (v != start as Vessel && IsTrackedAsteroid(v) && v.GetOrbit()?.referenceBody == b)
                            {
                                // Loop past the end of the array to provide a chance to
                                // append after the last entry.
                                for (int t = 0; t < transfers.Count + 1; ++t)
                                {
                                    if (t >= transfers.Count)
                                    {
                                        transfers.Add(new TransferModel(origin, v));
                                        if (v == targetBody)
                                        {
                                            foundTarget = true;
                                        }
                                        break;
                                    }
                                    else if (transfers[t].destination.GetOrbit().referenceBody == b &&
                                             (v.GetOrbit()?.semiMajorAxis ?? 0) < transfers[t].destination.GetOrbit().semiMajorAxis)
                                    {
                                        transfers.Insert(t, new TransferModel(origin, v));
                                        if (v == targetBody)
                                        {
                                            foundTarget = true;
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (toSkip == targetBody && targetBody != null)
                    {
                        DbgFmt("Found target as ancestor");
                        foundTarget = true;
                    }
                }

                if (!foundTarget &&
                    FlightGlobals.ActiveVessel != null &&
                    FlightGlobals.fetch.VesselTarget != null)
                {
                    DbgFmt("Allocating transfer to {0}", FlightGlobals.fetch.VesselTarget.GetName());
                    transfers.Insert(0, new TransferModel(origin, FlightGlobals.fetch.VesselTarget));
                }
            }
        }
Пример #26
0
        /// <summary>
        ///     Updates the details by recalculating if requested.
        /// </summary>
        public void Update()
        {
            ITargetable    target = null;
            global::Vessel vessel = null;

            landedSamePlanet = false;
            isLanded         = false;
            overrideANDN     = false;
            overrideANDNRev  = false;

            if (HighLogic.LoadedSceneIsFlight)
            {
                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;
                }
                else
                {
                    target = FlightGlobals.ActiveVessel.targetObject;
                    vessel = FlightGlobals.ActiveVessel;
                }
                TrackingStationSource = null;
            }
            else if (HighLogic.LoadedScene == GameScenes.TRACKSTATION)
            {
                if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.CelestialBody)
                {
                    target = PlanetariumCamera.fetch.target.celestialBody;
                }
                else if (PlanetariumCamera.fetch.target.type == MapObject.ObjectType.Vessel)
                {
                    target = PlanetariumCamera.fetch.target.vessel;
                }

                if (TrackingStationSource != null)
                {
                    vessel = TrackingStationSource.GetVessel();
                }
                else
                {
                    TrackingStationSource = target;
                }
            }

            activeTarget = target;

            if (target == null)
            {
                ShowDetails = false;
                return;
            }

            ShowDetails = true;

            var actualSourceOrbit = vessel != null ? vessel.orbit : TrackingStationSource.GetOrbit();
            var actualTargetOrbit = target.GetOrbit();

            if (target is global::Vessel)
            {
                targetVessel = (global::Vessel)target;
            }
            else
            {
                targetVessel = null;
            }

            activeVessel = vessel;

            if (actualSourceOrbit == null)
            {
                //  Debug.Log("Source orbit is null!");
                TrackingStationSource = null;
                ShowDetails           = false;
                return;
            }

            if (actualTargetOrbit == null)
            {
                // Debug.Log("Target orbit is null!");
                ShowDetails = false;
                return;
            }

            isLanded = vessel != null && vessel.LandedOrSplashed;
            bool targetLanded = (target is global::Vessel && ((global::Vessel)target).LandedOrSplashed);

            landedSamePlanet = isLanded && targetLanded && actualSourceOrbit.referenceBody == actualTargetOrbit.referenceBody;

            var originOrbit = isLanded ? actualSourceOrbit.referenceBody.orbit : actualSourceOrbit;
            var targetOrbit = targetLanded ? actualTargetOrbit.referenceBody.orbit : actualTargetOrbit;

            if ((!isLanded && !targetLanded) || (actualSourceOrbit.referenceBody != actualTargetOrbit.referenceBody))
            {
                findConcentricParents(ref originOrbit, ref targetOrbit);
            }

            if (originOrbit == targetOrbit && !landedSamePlanet)
            {
                targetOrbit = actualTargetOrbit;
                originOrbit = null;
            }

            { //These are not 'rendezvous' calculations, just raw data about the target object.
                AltitudeSeaLevel    = targetOrbit.altitude;
                ApoapsisHeight      = targetOrbit.ApA;
                PeriapsisHeight     = targetOrbit.PeA;
                TimeToApoapsis      = targetOrbit.timeToAp;
                TimeToPeriapsis     = targetOrbit.timeToPe;
                SemiMajorAxis       = targetOrbit.semiMajorAxis;
                SemiMinorAxis       = targetOrbit.semiMinorAxis;
                OrbitalPeriod       = targetOrbit.period;
                RelativeInclination = targetOrbit.inclination;
            }

            { //Set everything else 0 incase some are not valid.
                TimeToAscendingNode   = 0;
                TimeToDescendingNode  = 0;
                AngleToAscendingNode  = 0;
                AngleToDescendingNode = 0;

                RelativeVelocity    = 0;
                RelativeSpeed       = 0;
                PhaseAngle          = 0;
                InterceptAngle      = 0;
                TimeToTransferAngle = 0;

                AngleToPlane[0] = 0;
                TimeToPlane[0]  = 0;
                AngleToPlane[1] = 0;
                TimeToPlane[1]  = 0;
                Distance        = 0;

                TimeTilEncounter      = double.NaN;
                SeparationAtEncounter = double.NaN;
                SpeedAtEncounter      = double.NaN;

                Orbital.ManoeuvreNode.ManoeuvreProcessor.PostBurnRelativeInclination = 0;
            }


            if (originOrbit != null)   //Actually calculating an encounter with 2 different things.

            {
                overrideANDN       = isLanded && actualSourceOrbit.referenceBody == targetOrbit.referenceBody;
                overrideANDNRev    = targetLanded && !isLanded && actualTargetOrbit.referenceBody == actualSourceOrbit.referenceBody && target.GetVessel() != null;
                bodyRotationPeriod = actualSourceOrbit.referenceBody.rotationPeriod;

                if (landedSamePlanet)   //this should only occur when landed targeting something else landed on same body.

                {
                    AltitudeSeaLevel = target.GetVessel().altitude;
                    ApoapsisHeight   = 0;
                    PeriapsisHeight  = 0;
                    TimeToApoapsis   = 0;
                    TimeToPeriapsis  = 0;
                    SemiMajorAxis    = 0;
                    SemiMinorAxis    = 0;
                    Distance         = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D());
                    OrbitalPeriod    = bodyRotationPeriod;
                }
                else if (overrideANDN)    //launching

                {
                    if (vessel != null)
                    {
                        AngleToPlane   = CalcAngleToPlane(vessel.GetOrbit().referenceBody, vessel.latitude, vessel.longitude, targetOrbit);
                        TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                        TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                    }

                    RelativeInclination = targetOrbit.inclination;
                    PhaseAngle          = OrbitExtensions.GetPhaseAngle(actualSourceOrbit, actualTargetOrbit); //this works for some reason.
                }
                else if (overrideANDNRev)                                                                      //landing

                {
                    global::Vessel tgt = target.GetVessel();

                    if (vessel != null)
                    {
                        AngleToPlane   = CalcAngleToPlane(vessel.GetOrbit().referenceBody, tgt.latitude, tgt.longitude, originOrbit);
                        TimeToPlane[0] = (AngleToPlane[0] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                        TimeToPlane[1] = (AngleToPlane[1] / 360) * vessel.GetOrbit().referenceBody.rotationPeriod;
                    }

                    RelativeInclination = originOrbit.inclination;
                    Distance            = Vector3d.Distance(target.GetVessel().GetWorldPos3D(), vessel.GetWorldPos3D());
                    AltitudeSeaLevel    = tgt.altitude;
                    PhaseAngle          = OrbitExtensions.GetPhaseAngle(actualSourceOrbit, actualTargetOrbit); //this works for some reason.
                }
                else                                                                                           //standard 2 orbits

                {
                    RelativeInclination = OrbitExtensions.GetRelativeInclination(originOrbit, targetOrbit);



                    if (FlightGlobals.ActiveVessel == null || FlightGlobals.ActiveVessel.patchedConicSolver == null ||
                        FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes == null ||
                        FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes.Count == 0)
                    {
                    }
                    else
                    {
                        var node = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0];
                        if (node != null && node.nextPatch != null)
                        {
                            Orbital.ManoeuvreNode.ManoeuvreProcessor.PostBurnRelativeInclination = OrbitExtensions.GetRelativeInclination(node.nextPatch, FlightGlobals.ActiveVessel.targetObject.GetOrbit());
                        }
                    }



                    RelativeSpeed    = originOrbit.GetRelativeVel().magnitude - target.GetObtVelocity().magnitude;
                    RelativeVelocity = (originOrbit.GetRelativeVel() - target.GetObtVelocity()).magnitude;

                    // FlightGlobals.ship_tgtVelocity = FlightGlobals.ship_obtVelocity - this.VesselTarget.GetObtVelocity();
                    // FlightGlobals.ship_tgtSpeed = FlightGlobals.ship_tgtVelocity.magnitude;

                    PhaseAngle     = OrbitExtensions.GetPhaseAngle(originOrbit, targetOrbit);
                    InterceptAngle = CalcInterceptAngle(targetOrbit, originOrbit);

                    double tspd = 360 / targetOrbit.period;
                    double sspd = 360 / originOrbit.period;

                    if (PhaseAngle < 0)
                    {
                        double diff = InterceptAngle - PhaseAngle;
                        if (diff < 0)
                        {
                            diff += 360;
                        }
                        if (diff > 340)
                        {
                            diff -= 360;
                        }
                        TimeToTransferAngle = sspd == tspd ? 0 : diff / (tspd - sspd);
                    }
                    else
                    {
                        double diff = PhaseAngle - InterceptAngle;
                        if (diff < 0)
                        {
                            diff += 360;
                        }
                        if (diff > 340)
                        {
                            diff -= 360;
                        }
                        TimeToTransferAngle = sspd == tspd ? 0 : diff / (sspd - tspd);
                    }


                    TimeToAscendingNode   = OrbitExtensions.GetTimeToVector(originOrbit, GetAscendingNode(targetOrbit, originOrbit));
                    TimeToDescendingNode  = OrbitExtensions.GetTimeToVector(originOrbit, GetDescendingNode(targetOrbit, originOrbit));
                    AngleToAscendingNode  = OrbitExtensions.GetAngleToVector(originOrbit, GetAscendingNode(targetOrbit, originOrbit));
                    AngleToDescendingNode = OrbitExtensions.GetAngleToVector(originOrbit, GetDescendingNode(targetOrbit, originOrbit));

                    Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos);


                    //From OrbitTargeter
                    double tOne = 0;
                    if (target is CelestialBody)
                    {
                        Vector3d relativePositionAtUT  = originOrbit.getRelativePositionAtUT(originOrbit.closestTgtApprUT);
                        Vector3d relativePositionAtUT2 = targetOrbit.getRelativePositionAtUT(originOrbit.closestTgtApprUT);
                        double   separation            = (relativePositionAtUT - relativePositionAtUT2).magnitude;
                        tOne = originOrbit.closestTgtApprUT;
                    }
                    else
                    {
                        double num3       = 0.0;
                        double num4       = 0.0;
                        double num5       = 0.0;
                        double eVs        = 0.0;
                        double num6       = 0.0;
                        double eVs2       = 0.0;
                        int    iterations = 0;
                        int    num7       = Orbit.FindClosestPoints(originOrbit, targetOrbit, ref num3, ref num4, ref num5, ref eVs, ref num6, ref eVs2, 0.0001, 20, ref iterations);
                        tOne = originOrbit.StartUT + originOrbit.GetDTforTrueAnomaly(num5, 0.0);
                        double tTwo = originOrbit.StartUT + originOrbit.GetDTforTrueAnomaly(num6, 0.0);
                        if (tOne > tTwo)
                        {
                            UtilMath.SwapValues(ref tOne, ref tTwo);
                            UtilMath.SwapValues(ref num5, ref num6);
                            UtilMath.SwapValues(ref eVs, ref eVs2);
                        }
                    }

                    if (tOne > originOrbit.StartUT)
                    {
                        TimeTilEncounter      = tOne - originOrbit.StartUT;
                        SeparationAtEncounter = (originOrbit.getPositionAtUT(tOne) - targetOrbit.getPositionAtUT(tOne)).magnitude;
                        SpeedAtEncounter      = Math.Abs(originOrbit.getOrbitalSpeedAt(tOne) - targetOrbit.getOrbitalSpeedAt(tOne));
                    }
                }
            }

            if (actualTargetOrbit != targetOrbit)
            {
                targetDisplay = findNameForOrbit(targetOrbit, target);
            }
            else
            {
                targetDisplay = null;
            }

            if (originOrbit == null)
            {
                sourceDisplay = "N/A";
            }
            else if (actualSourceOrbit != originOrbit || HighLogic.LoadedScene == GameScenes.TRACKSTATION)
            {
                sourceDisplay = findNameForOrbit(originOrbit, vessel != null ? vessel : TrackingStationSource);
            }
            else
            {
                sourceDisplay = null;
            }
        }
Пример #27
0
        /// <summary>
        ///     Draws the target information when selected.
        /// </summary>
        private void DrawTarget(Unity.Flight.ISectionModule section)
        {
            ITargetable target = Flight.Readouts.Rendezvous.RendezvousProcessor.activeTarget;

            this.ResizeRequested = true;

            if (target != null)
            {
                if (HighLogic.LoadedSceneIsFlight)
                {
                    if (GUILayout.Button("Go Back to Target Selection", this.ButtonStyle, GUILayout.Width(this.ContentWidth)))
                    {
                        FlightGlobals.fetch.SetVesselTarget(null);
                    }
                }
                else
                {
                    if (RendezvousProcessor.TrackingStationSource != target)
                    {
                        if (GUILayout.Button("Use " + RendezvousProcessor.nameForTargetable(target) + " As Reference", this.ButtonStyle, GUILayout.Width(this.ContentWidth)))
                        {
                            RendezvousProcessor.TrackingStationSource = target;
                        }
                    }
                }

                if (HighLogic.LoadedSceneIsFlight)
                {
                    var act = FlightGlobals.ActiveVessel;

                    if (!(target is CelestialBody) && GUILayout.Button("Switch to Target", this.ButtonStyle, GUILayout.Width(this.ContentWidth)))
                    {
                        FlightEngineerCore.SwitchToVessel(target.GetVessel(), act);
                    }

                    bool focusable = (target is CelestialBody || target is global::Vessel);

                    if (focusable)
                    {
                        MapObject targMo = null;

                        if (target is global::Vessel)
                        {
                            targMo = ((global::Vessel)(target)).mapObject;
                        }
                        else
                        {
                            targMo = ((CelestialBody)(target)).MapObject;
                        }

                        bool shouldFocus = targMo != null && (targMo != PlanetariumCamera.fetch.target || !MapView.MapIsEnabled);

                        if (shouldFocus && GUILayout.Button("Focus Target", this.ButtonStyle, GUILayout.Width(this.ContentWidth)))
                        {
                            wasMapview = MapView.MapIsEnabled;
                            MapView.EnterMapView();
                            PlanetariumCamera.fetch.SetTarget(targMo);
                        }
                    }

                    bool switchBack = PlanetariumCamera.fetch.target != act.mapObject;

                    if (switchBack && MapView.MapIsEnabled && GUILayout.Button("Focus Vessel", this.ButtonStyle, GUILayout.Width(this.ContentWidth)))
                    {
                        if (!wasMapview)
                        {
                            MapView.ExitMapView();
                        }
                        PlanetariumCamera.fetch.SetTarget(act.mapObject);
                    }

                    if (FlightCamera.fetch.mode != FlightCamera.Modes.LOCKED && !MapView.MapIsEnabled && GUILayout.Button("Look at Target", this.ButtonStyle, GUILayout.Width(this.ContentWidth)))
                    {
                        var pcam = PlanetariumCamera.fetch;
                        var fcam = FlightCamera.fetch;

                        Vector3 from = new Vector3();

                        if (target is global::Vessel && ((global::Vessel)target).LandedOrSplashed)
                        {
                            from = ((global::Vessel)target).GetWorldPos3D();
                        }
                        else
                        {
                            //I don't think it's possible to target the sun so this should always work but who knows.
                            if (target.GetOrbit() != null)
                            {
                                from = target.GetOrbit().getTruePositionAtUT(Planetarium.GetUniversalTime());
                            }
                        }


                        Vector3 to = FlightGlobals.fetch.activeVessel.GetWorldPos3D();

                        //  float pdist = pcam.Distance;
                        float fdist = fcam.Distance;

                        Vector3 n = (from - to).normalized;

                        if (!n.IsInvalid())
                        {
                            //   pcam.SetCamCoordsFromPosition(n * -pdist); //this does weird stuff
                            fcam.SetCamCoordsFromPosition(n * -fdist);
                        }
                    }
                }

                GUILayout.Space(3f);

                this.DrawLine("Selected Target", RendezvousProcessor.nameForTargetable(target), section.IsHud);

                if (RendezvousProcessor.sourceDisplay != null)
                {
                    if (RendezvousProcessor.landedSamePlanet || RendezvousProcessor.overrideANDN)
                    {
                        this.DrawLine("Ref Orbit", "Landed on " + RendezvousProcessor.activeVessel.GetOrbit().referenceBody.GetName(), section.IsHud);
                    }
                    else
                    {
                        this.DrawLine("Ref Orbit", RendezvousProcessor.sourceDisplay, section.IsHud);
                    }
                }

                if (RendezvousProcessor.targetDisplay != null)
                {
                    if (RendezvousProcessor.landedSamePlanet || RendezvousProcessor.overrideANDNRev)
                    {
                        this.DrawLine("Target Orbit", "Landed on " + target.GetOrbit().referenceBody.GetName(), section.IsHud);
                    }
                    else
                    {
                        this.DrawLine("Target Orbit", RendezvousProcessor.targetDisplay, section.IsHud);
                    }
                }
            }
        }
Пример #28
0
        public static void Add(Kerbulator kalc)
        {
            // Planets
            foreach (CelestialBody b in FlightGlobals.Bodies)
            {
                if (b.name == "Sun")
                {
                    AddCelestialBody(kalc, b, "Sun");
                    AddCelestialBody(kalc, b, "Kerbol");
                }
                else
                {
                    AddCelestialBody(kalc, b, b.name);
                }
            }

            // Current time
            double UT = (double)Planetarium.GetUniversalTime();

            AddDouble(kalc, "UT", UT);

            Vessel v = FlightGlobals.ActiveVessel;

            if (v != null)
            {
                // Mission time
                AddDouble(kalc, "MissionTime", v.missionTime);

                // Current orbit
                Orbit orbit1 = v.orbit;
                AddOrbit(kalc, orbit1, "Craft");

                // Navball (thank you MechJeb source)
                Vector3    CoM                   = v.CoM;
                Vector3    up                    = v.up;
                Vector3    north                 = v.north;
                Quaternion rotationSurface       = Quaternion.LookRotation(north, up);
                Quaternion rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(v.GetTransform().rotation) * rotationSurface);
                Vector3    velocityVesselOrbit   = v.orbit.GetVel();
                Vector3    velocityVesselSurface = velocityVesselOrbit - v.mainBody.getRFrmVel(CoM);

                AddDouble(kalc, "Navball.Heading", rotationVesselSurface.eulerAngles.y);
                AddDouble(kalc, "Navball.Pitch", (rotationVesselSurface.eulerAngles.x > 180) ? (360.0 - rotationVesselSurface.eulerAngles.x) : -rotationVesselSurface.eulerAngles.x);
                AddDouble(kalc, "Navball.Roll", (rotationVesselSurface.eulerAngles.z > 180) ? (rotationVesselSurface.eulerAngles.z - 360.0) : rotationVesselSurface.eulerAngles.z);
                AddDouble(kalc, "Navball.OrbitalVelocity", velocityVesselOrbit.magnitude);
                AddDouble(kalc, "Navball.SurfaceVelocity", v.srfSpeed);
                AddDouble(kalc, "Navball.VerticalVelocity", v.verticalSpeed);

                // Reference body
                AddCelestialBody(kalc, v.orbit.referenceBody, "Parent");

                // Target
                if (FlightGlobals.fetch.VesselTarget != null)
                {
                    ITargetable target = FlightGlobals.fetch.VesselTarget;
                    Orbit       orbit2 = target.GetOrbit();

                    // Target Orbit
                    AddOrbit(kalc, orbit2, "Target");

                    // Intersection with target orbit
                    double CD             = 0.0;
                    double CCD            = 0.0;
                    double FFp            = 0.0;
                    double FFs            = 0.0;
                    double SFp            = 0.0;
                    double SFs            = 0.0;
                    int    iterationCount = 0;
                    Orbit.FindClosestPoints(orbit1, orbit2, ref CD, ref CCD, ref FFp, ref FFs, ref SFp, ref SFs, 0.0, 100, ref iterationCount);
                    double t1 = orbit1.GetDTforTrueAnomaly(FFp, 0.0);
                    double t2 = orbit1.GetDTforTrueAnomaly(SFp, 0.0);
                    double T1 = Math.Min(t1, t2);
                    double T2 = Math.Max(t1, t2);

                    AddDouble(kalc, "Craft.Inter1.dt", T1);
                    AddDouble(kalc, "Craft.Inter1.Δt", T1);
                    AddDouble(kalc, "Craft.Inter1.Sep", (orbit1.getPositionAtUT(T1 + UT) - orbit2.getPositionAtUT(T1 + UT)).magnitude);
                    AddDouble(kalc, "Craft.Inter1.TrueAnomaly", orbit1.TrueAnomalyAtUT(T1 + UT) * (180 / Math.PI));
                    AddDouble(kalc, "Craft.Inter1.θ", orbit1.TrueAnomalyAtUT(T1 + UT) * (180 / Math.PI));
                    AddDouble(kalc, "Craft.Inter2.dt", T2);
                    AddDouble(kalc, "Craft.Inter2.Δt", T2);
                    AddDouble(kalc, "Craft.Inter2.Sep", (orbit1.getPositionAtUT(T2 + UT) - orbit2.getPositionAtUT(T2 + UT)).magnitude);
                    AddDouble(kalc, "Craft.Inter2.TrueAnomaly", orbit2.TrueAnomalyAtUT(T2 + UT) * (180 / Math.PI));
                    AddDouble(kalc, "Craft.Inter2.θ", orbit2.TrueAnomalyAtUT(T2 + UT) * (180 / Math.PI));
                    // Relative Ascending and Descending Nodes, Inclination
                    AddDouble(kalc, "Craft.Rel.AN", orbit1.GetTrueAnomalyOfZupVector(Vector3.Cross(orbit2.GetOrbitNormal(), orbit1.GetOrbitNormal())) * (180 / Math.PI));
                    AddDouble(kalc, "Craft.Rel.DN", orbit1.GetTrueAnomalyOfZupVector(Vector3.Cross(orbit1.GetOrbitNormal(), orbit2.GetOrbitNormal())) * (180 / Math.PI));
                    AddDouble(kalc, "Craft.Rel.Inc", Vector3.Angle(orbit1.GetOrbitNormal(), orbit2.GetOrbitNormal()));
                }
            }
        }