private void CalcPhaseAngleTarget() { _PhaseAngleTarget = KACUtils.clampDegrees360(180 * (1 - Math.Pow((Origin.orbit.semiMajorAxis + Target.orbit.semiMajorAxis) / (2 * Target.orbit.semiMajorAxis), 1.5))); }
private void CalcPhaseAngleCurrent() { _PhaseAngleCurrent = KACUtils.clampDegrees360(Target.orbit.trueAnomaly + Target.orbit.argumentOfPeriapsis + Target.orbit.LAN - (Origin.orbit.trueAnomaly + Origin.orbit.argumentOfPeriapsis + Origin.orbit.LAN)); }
private void WindowLayout_AddPane_ClosestApproach() { GUILayout.BeginVertical(); GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading); if (KACWorkerGameState.CurrentVessel == null) { GUILayout.Label("No Active Vessel"); } else { if (!(KACWorkerGameState.CurrentVesselTarget is Vessel) && !(KACWorkerGameState.CurrentVesselTarget is ModuleDockingNode)) { GUILayout.Label("No valid Vessel Target Selected", GUILayout.ExpandWidth(true)); } else { //GUILayout.Label("Adjust Lookahead amounts...", KACResources.styleAddSectionHeading); GUILayout.BeginVertical(KACResources.styleAddFieldAreas); GUILayout.BeginHorizontal(); GUILayout.Label("Orbits to Search:", KACResources.styleAddHeading, GUILayout.Width(110)); GUILayout.Label(((int)Math.Round((Decimal)fltOrbits, 0)).ToString(), KACResources.styleAddXferName, GUILayout.Width(25)); fltOrbits = GUILayout.HorizontalSlider(fltOrbits, 1, 20); fltOrbits = (float)Math.Floor((Decimal)fltOrbits); GUILayout.EndHorizontal(); intOrbits = (int)fltOrbits; int intClosestOrbitPass = 0; double dblClosestDistance = Double.MaxValue; double dblClosestUT = 0; double dblOrbitTestClosest = Double.MaxValue; double dblOrbitTestClosestUT = 0; for (int intOrbitToTest = 1; intOrbitToTest <= intOrbits; intOrbitToTest++) { dblOrbitTestClosestUT = KACUtils.timeOfClosestApproach(KACWorkerGameState.CurrentVessel.orbit, KACWorkerGameState.CurrentVesselTarget.GetOrbit(), KACWorkerGameState.CurrentTime.UT, intOrbitToTest, out dblOrbitTestClosest ); if (dblOrbitTestClosest < dblClosestDistance) { dblClosestDistance = dblOrbitTestClosest; dblClosestUT = dblOrbitTestClosestUT; intClosestOrbitPass = intOrbitToTest; } } GUILayout.BeginHorizontal(); GUILayout.Label("Distance:", 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)); GUILayout.Label("On Orbit:", KACResources.styleAddHeading); GUILayout.Label(intClosestOrbitPass.ToString(), KACResources.styleAddXferName); GUILayout.EndHorizontal(); GUILayout.EndVertical(); String strMarginConversion = ""; KACTime eventTime = new KACTime(dblClosestUT); KACTime eventInterval = new KACTime(dblClosestUT - 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 Future Closest Approach found"; } if (strMarginConversion != "") { GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true)); } } } GUILayout.EndVertical(); }
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 CalcPhaseAngleCurrent2() { _PhaseAngleCurrent = KACUtils.clampDegrees360((Target.orbit.trueAnomaly * Mathf.Rad2Deg) + Target.orbit.argumentOfPeriapsis + Target.orbit.LAN - ((Origin.orbit.trueAnomaly * Mathf.Rad2Deg) + Origin.orbit.argumentOfPeriapsis + Origin.orbit.LAN)); }
internal static KACAlarm LoadFromString3(String AlarmDetails, Double CurrentUT) { //String is "VesselID|Name|Notes|AlarmTime.UT|AlarmMarginSecs|Type|Enabled|HaltWarp|PauseGame|ActionedAt|Maneuver|Xfer|Target|Options|<ENDLINE>"); String[] vars = AlarmDetails.Split("|".ToCharArray(), StringSplitOptions.None); Log.dbg("AlarmExtract"); for (int i = 0; i < vars.Length; i++) { Log.dbg("{0}:{1}", i, vars[i]); } //String SaveName = HighLogic.CurrentGame.Title; //Commented because usage removed String VesselID = vars[0]; String Name = KACUtils.DecodeVarStrings(vars[1]); String Notes = KACUtils.DecodeVarStrings(vars[2]); Double UT = Convert.ToDouble(vars[3]); Double AlarmMarginSecs = Convert.ToDouble(vars[4]); KACAlarm.AlarmTypeEnum TypeOfAlarm = (KACAlarm.AlarmTypeEnum)Enum.Parse(typeof(KACAlarm.AlarmTypeEnum), vars[5]); Boolean Enabled = Convert.ToBoolean(vars[6]); Boolean HaltWarp = Convert.ToBoolean(vars[7]); Boolean PauseGame = Convert.ToBoolean(vars[8]); Double ActionedAt = Convert.ToDouble(vars[9]); List <ManeuverNode> ManNodes = null; String XferOriginBodyName = "", XferTargetBodyName = ""; ITargetable TargetObject = null; String TargetLoader = ""; Boolean Triggered = false, Actioned = false, AlarmWindowClosed = false; if (vars[10] != "") { ManNodes = ManNodeDeserializeList(vars[10]); } if (vars[11] != "") { try { Log.dbg("{0}", vars[11]); String[] XferParts = vars[11].Split(",".ToCharArray()); XferOriginBodyName = XferParts[0]; XferTargetBodyName = XferParts[1]; } catch (Exception ex) { Log.dbg("Unable to load transfer details for {0}", Name); Log.dbg(ex.Message); } } if (vars[12] != "") { //find the targetable object and set it TargetObject = TargetDeserialize(vars[12]); if (TargetObject == null && vars[12].StartsWith("Vessel,")) { TargetLoader = vars[12]; } } //Now do the work to set Actioned/triggered/etc if needed //LogFormatted("A:{0},T:{1:0},Act:{2:0}", this.Name, CurrentUT, this.ActionedAt); if (ActionedAt > 0 && CurrentUT > ActionedAt) { Log.dbg("Suppressing Alarm on Load:{0}", Name); Triggered = true; Actioned = true; AlarmWindowClosed = true; } else if (ActionedAt > CurrentUT) { Log.dbg("Reenabling Alarm on Load:{0}", Name); Triggered = false; Actioned = false; ActionedAt = 0; AlarmWindowClosed = false; } KACAlarm resultAlarm = new KACAlarm(UT); resultAlarm.Name = Name; resultAlarm.VesselID = VesselID; resultAlarm.Enabled = Enabled; resultAlarm.Notes = Notes; resultAlarm.AlarmMarginSecs = AlarmMarginSecs; resultAlarm.TypeOfAlarm = TypeOfAlarm; if (HaltWarp) { resultAlarm.AlarmActionConvert = KACAlarm.AlarmActionEnum.KillWarp; } else if (PauseGame) { resultAlarm.AlarmActionConvert = KACAlarm.AlarmActionEnum.PauseGame; } if (ManNodes != null) { resultAlarm.ManNodes = ManNodes; } if (TargetObject != null) { resultAlarm.TargetObject = TargetObject; } resultAlarm.TargetLoader = TargetLoader; resultAlarm.XferOriginBodyName = XferOriginBodyName; resultAlarm.XferTargetBodyName = XferTargetBodyName; resultAlarm.Triggered = Triggered; resultAlarm.Actioned = Actioned; resultAlarm.AlarmWindowClosed = AlarmWindowClosed; return(resultAlarm); }
internal override void OnPreCull() { base.OnPreCull(); //not sure if this is right - but its working if (!KerbalAlarmClock.lstScenesForAngles.Contains(HighLogic.LoadedScene)) { return; } if (MapView.MapIsEnabled && isDrawing) { //Get the Vector of the Origin body from the ref point and its distance Vector3d vectStart = bodyOrigin.transform.position - bodyOrigin.referenceBody.transform.position; Double vectStartMag = vectStart.magnitude; //now work out the angle //Double _PhaseAngleCurrent = ClampDegrees180(LambertSolver.CurrentPhaseAngle(bodyOrigin.orbit,bodyTarget.orbit)); _PhaseAngleCurrent = KACUtils.CurrentPhaseAngle(bodyOrigin.orbit, bodyTarget.orbit); if (bodyTarget.orbit.semiMajorAxis < bodyOrigin.orbit.semiMajorAxis) { _PhaseAngleCurrent = _PhaseAngleCurrent - 360; } //And therefore the 2nd arm of the angle Vector3d vectEnd = Quaternion.AngleAxis(-(Single)_PhaseAngleCurrent, bodyOrigin.orbit.GetOrbitNormal().xzy) * vectStart; //make it 120% of the target bodies orbit vectEnd = vectEnd.normalized * bodyTarget.orbit.ApR * 1.2; Double vectEndMag = vectEnd.magnitude; Vector3d vectPointEnd = bodyOrigin.referenceBody.transform.position + vectEnd; //and heres the three points vectPosWorldPivot = bodyOrigin.referenceBody.transform.position; vectPosWorldOrigin = bodyOrigin.transform.position; vectPosWorldEnd = vectPointEnd; if (ShowTargetAngle) { Vector3d vectTarget = Quaternion.AngleAxis(-(Single)AngleTargetValue, bodyOrigin.orbit.GetOrbitNormal().xzy) * vectStart; vectPosWorldTarget = vectTarget.normalized * vectEndMag * 0.9; vectPosWorldTarget += bodyOrigin.referenceBody.transform.position; } //Are we Showing, Hiding or Static State if (_isHiding) { Single pctDone = (Single)(DateTime.Now - StartDrawing).TotalSeconds / 0.25f; if (pctDone >= 1) { _isHiding = false; isDrawing = false; } vectPosPivotWorking = bodyOrigin.transform.position - Mathf.Lerp(0, (Single)vectStartMag, Mathf.Clamp01(pctDone)) * vectStart.normalized; DrawLine(lineStart, vectPosWorldPivot, vectPosWorldPivot + (vectPosWorldOrigin - vectPosWorldPivot).normalized * Mathf.Lerp((Single)vectStartMag, 0, pctDone)); DrawLine(lineEnd, vectPosWorldPivot, vectPosWorldPivot + (vectPosWorldEnd - vectPosWorldPivot).normalized * Mathf.Lerp((Single)vectEndMag, 0, pctDone)); DrawArc(lineArc, vectStart, _PhaseAngleCurrent, Mathf.Lerp((Single)bodyOrigin.orbit.radius, 0, pctDone), Mathf.Lerp((Single)bodyTarget.orbit.radius, 0, pctDone)); if (ShowTargetAngle) { DrawLine(lineTarget, vectPosWorldPivot, vectPosWorldPivot + (vectPosWorldTarget - vectPosWorldPivot).normalized * Mathf.Lerp((Single)vectEndMag, 0, pctDone)); DrawArc(lineTargetArc, vectStart, AngleTargetValue, Mathf.Lerp((Single)bodyOrigin.orbit.radius * 0.9f, 0, pctDone), Mathf.Lerp((Single)bodyTarget.orbit.radius * 0.9f, 0, pctDone)); } } else if (isBecomingVisible) { if (!_isBecomingVisible_LinesDone) { Single pctDone = (Single)(DateTime.Now - StartDrawing).TotalSeconds / 0.5f; if (pctDone >= 1) { _isBecomingVisible_LinesDone = true; StartDrawing = DateTime.Now; } vectPosPivotWorking = bodyOrigin.transform.position - Mathf.Lerp(0, (Single)vectStartMag, Mathf.Clamp01(pctDone)) * vectStart.normalized; DrawLine(lineStart, vectPosPivotWorking, vectPosWorldOrigin); } else if (!_isBecomingVisible_ArcDone) { Single pctDone = (Single)(DateTime.Now - StartDrawing).TotalSeconds / 0.5f; if (pctDone >= 1) { _isBecomingVisible_ArcDone = true; StartDrawing = DateTime.Now; } Double vectEndMagWorking = Mathf.Lerp((Single)vectStartMag, (Single)vectEndMag, Mathf.Clamp01(pctDone)); Double PhaseAngleWorking = Mathf.Lerp(0, (Single)_PhaseAngleCurrent, Mathf.Clamp01(pctDone)); vectPosEndWorking = (Vector3d)(Quaternion.AngleAxis(-(Single)PhaseAngleWorking, bodyOrigin.orbit.GetOrbitNormal().xzy) * vectStart).normalized * vectEndMagWorking; vectPosEndWorking += bodyOrigin.referenceBody.transform.position; //draw the origin and end lines DrawLine(lineStart, vectPosWorldPivot, vectPosWorldOrigin); DrawLine(lineEnd, vectPosWorldPivot, vectPosEndWorking); DrawArc(lineArc, vectStart, PhaseAngleWorking, bodyOrigin.orbit.radius, bodyTarget.orbit.radius); } else if (!_isBecomingVisible_TargetArcDone) { if (!ShowTargetAngle) { _isBecomingVisible_TargetArcDone = true; _isBecomingVisible = false; } else { Single pctDone = (Single)(DateTime.Now - StartDrawing).TotalSeconds / 0.5f; if (pctDone >= 1) { _isBecomingVisible_TargetArcDone = true; _isBecomingVisible = false; } Double PhaseAngleWorking = Mathf.Lerp(0, (Single)AngleTargetValue, Mathf.Clamp01(pctDone)); vectPosTargetWorking = (Vector3d)(Quaternion.AngleAxis(-(Single)PhaseAngleWorking, bodyOrigin.orbit.GetOrbitNormal().xzy) * vectStart).normalized * vectEndMag * 0.9; vectPosTargetWorking += bodyOrigin.referenceBody.transform.position; DrawLine(lineStart, vectPosWorldPivot, vectPosWorldOrigin); DrawLine(lineEnd, vectPosWorldPivot, vectPosWorldEnd); DrawArc(lineArc, vectStart, _PhaseAngleCurrent, bodyOrigin.orbit.radius, bodyTarget.orbit.radius); DrawLine(lineTarget, vectPosWorldPivot, vectPosTargetWorking); DrawArc(lineTargetArc, vectStart, PhaseAngleWorking, bodyOrigin.orbit.radius * 0.9, bodyTarget.orbit.radius * 0.9); } } } else { DrawLine(lineStart, vectPosWorldPivot, vectPosWorldOrigin); DrawLine(lineEnd, vectPosWorldPivot, vectPosWorldEnd); DrawArc(lineArc, vectStart, _PhaseAngleCurrent, bodyOrigin.orbit.radius, bodyTarget.orbit.radius);// vectStartMag, vectEndMag); if (ShowTargetAngle) { DrawLine(lineTarget, vectPosWorldPivot, vectPosWorldTarget); DrawArc(lineTargetArc, vectStart, AngleTargetValue, bodyOrigin.orbit.radius * 0.9, bodyTarget.orbit.radius * 0.9); } } } else { lineStart.enabled = false; lineEnd.enabled = false; lineArc.enabled = false; lineTarget.enabled = false; lineTargetArc.enabled = false; } }