private static bool GetClosestVessel(Orbit refP, Orbit tgtP) { if (refP == null || tgtP == null) { return(false); } if (refP.referenceBody != tgtP.referenceBody) { return(false); } if (!Orbit.PeApIntersects(refP, tgtP, 20000)) { return(false); } double d1 = 0; double d2 = 0; double dT1 = 0; double d4 = 0; double dT2 = 0; double d6 = 0; int i1 = 0; int intersects = Orbit.FindClosestPoints(refP, tgtP, ref d1, ref d2, ref dT1, ref d4, ref dT2, ref d6, 0.001, 10, ref i1); double UT1 = refP.StartUT + refP.GetDTforTrueAnomaly(dT1, 0); double UT2 = refP.StartUT + refP.GetDTforTrueAnomaly(dT2, 0); if (intersects > 1) { double dist1 = double.MaxValue; if (PatchedConics.TAIsWithinPatchBounds(UT1, refP)) { Vector3d refClosest1 = refP.getRelativePositionAtUT(UT1); Vector3d tgtClosest1 = tgtP.getRelativePositionAtUT(UT1); dist1 = (refClosest1 - tgtClosest1).magnitude; } double dist2 = double.MaxValue; if (PatchedConics.TAIsWithinPatchBounds(UT2, refP)) { Vector3d refClosest2 = refP.getRelativePositionAtUT(UT2); Vector3d tgtClosest2 = tgtP.getRelativePositionAtUT(UT2); dist2 = (refClosest2 - tgtClosest2).magnitude; } if (dist1 > double.MaxValue - 1000 && dist2 > double.MaxValue - 1000) { return(false); } bool first = dist1 < dist2; if (first) { _closestDist = dist1; _closestTime = UT1; Vector3d refVel = refP.getOrbitalVelocityAtUT(UT1); Vector3d tgtVel = tgtP.getOrbitalVelocityAtUT(UT1); _closestRelVel = (refVel - tgtVel).magnitude; } else { _closestDist = dist2; _closestTime = UT2; Vector3d refVel = refP.getOrbitalVelocityAtUT(UT2); Vector3d tgtVel = tgtP.getOrbitalVelocityAtUT(UT2); _closestRelVel = (refVel - tgtVel).magnitude; } return(true); } else { if (!PatchedConics.TAIsWithinPatchBounds(UT1, refP)) { UT1 = double.MaxValue; } if (!PatchedConics.TAIsWithinPatchBounds(UT2, refP)) { UT2 = double.MaxValue; } if (UT1 > double.MaxValue - 1000 && UT2 > double.MaxValue - 1000) { return(false); } double useUT = UT1 < UT2 ? UT1 : UT2; Vector3d refClosest = refP.getRelativePositionAtUT(useUT); Vector3d tgtClosest = tgtP.getRelativePositionAtUT(useUT); Vector3d refVel = refP.getOrbitalVelocityAtUT(useUT); Vector3d tgtVel = tgtP.getOrbitalVelocityAtUT(useUT); _closestDist = (refClosest - tgtClosest).magnitude; _closestRelVel = (refVel - tgtVel).magnitude; _closestTime = useUT; return(true); } }
public static double closestVessel(double UT, Orbit o, Orbit tgt, bool closest, double min, double max) { double appUT = 0; if (o.referenceBody != tgt.referenceBody) { return(0); } if (!Orbit.PeApIntersects(o, tgt, 20000)) { return(0); } double d1 = 0; double d2 = 0; double dT1 = 0; double d4 = 0; double dT2 = 0; double d6 = 0; int i1 = 0; int intersects = Orbit.FindClosestPoints(o, tgt, ref d1, ref d2, ref dT1, ref d4, ref dT2, ref d6, 0.001, 10, ref i1); double UT1 = o.StartUT + o.GetDTforTrueAnomaly(dT1, 0); double UT2 = o.StartUT + o.GetDTforTrueAnomaly(dT2, 0); if (intersects > 1) { double dist1 = double.MaxValue; if (PatchedConics.TAIsWithinPatchBounds(UT1, o)) { Vector3d refClosest1 = o.getRelativePositionAtUT(UT1); Vector3d tgtClosest1 = tgt.getRelativePositionAtUT(UT1); dist1 = (refClosest1 - tgtClosest1).magnitude; } double dist2 = double.MaxValue; if (PatchedConics.TAIsWithinPatchBounds(UT2, o)) { Vector3d refClosest2 = o.getRelativePositionAtUT(UT2); Vector3d tgtClosest2 = tgt.getRelativePositionAtUT(UT2); dist2 = (refClosest2 - tgtClosest2).magnitude; } if (dist1 > double.MaxValue - 1000 && dist2 > double.MaxValue - 1000) { return(0); } appUT = dist1 < dist2 ? UT1 : UT2; if (closest) { return(appUT); } if (appUT >= min && appUT <= max) { return(appUT); } appUT = dist1 < dist2 ? UT2 : UT1; if (appUT >= min && appUT <= max) { return(appUT); } } else { if (!PatchedConics.TAIsWithinPatchBounds(UT1, o)) { UT1 = double.MaxValue; } if (!PatchedConics.TAIsWithinPatchBounds(UT2, o)) { UT2 = double.MaxValue; } if (UT1 > double.MaxValue - 1000 && UT2 > double.MaxValue - 1000) { return(0); } appUT = UT1 < UT2 ? UT1 : UT2; return(appUT); } return(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)); } } }
/// <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; } }
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())); } } }