From ecf7147357fe0a048ae125a209f98e955d050eab Mon Sep 17 00:00:00 2001 From: arthomnix Date: Fri, 3 Apr 2026 02:59:22 +0100 Subject: [PATCH] handle SOI changes correctly --- OemLoader/MainWindow.cs | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/OemLoader/MainWindow.cs b/OemLoader/MainWindow.cs index 5f10686..5e5697f 100644 --- a/OemLoader/MainWindow.cs +++ b/OemLoader/MainWindow.cs @@ -12,7 +12,7 @@ public class MainWindow(string title) private readonly ImInputString _filename = new(short.MaxValue); private List? _oem; private string? _errorMessage; - private long _sliderTicks = 0; + private long _sliderTicks; private void GoToTime(DateTime time) { @@ -20,9 +20,35 @@ public class MainWindow(string title) if (_oem.First().Epoch > time || time > _oem.Last().Epoch) return; var l = _oem.TakeWhile(line => line.Epoch <= time).Last(); - var orb = l.AsOrbit(Program.ControlledVehicle.Parent, - Program.ControlledVehicle.Orbit.OrbitLineColor); - var dt = (time - OemLoader.KsaEpoch).TotalSeconds - Universe.GetElapsedSeconds(); + + // Assume the ephemeris is for the home body of the system (i.e. Earth), fall back to vehicle's current parent + // if null + var body = Universe.CurrentSystem?.HomeBody ?? Program.ControlledVehicle.Parent; + var orb = l.AsOrbit(body, Program.ControlledVehicle.Orbit.OrbitLineColor); + var simTime = new SimTime((time - OemLoader.KsaEpoch).TotalSeconds); + + // If the position at the provided time is within the SOI of a child body, transform the orbit to + // an orbit around the child body. + // (Code mostly stolen from KSA.KinematicStates.CheckSoiTransitions) + var posCci = orb.GetStateVectorsAt(simTime).PositionCci; + foreach (var child in body.Children) + { + if (child is not Celestial childCelestial) continue; + var soi = childCelestial.SphereOfInfluence; + var childPos = child.GetPositionOrb(simTime).Transform(childCelestial.Orbit.GetOrb2ParentCci()); + var distance = (posCci - childPos).Length(); + + if (distance > soi) continue; + var rotation = doubleQuat.Concatenate(childCelestial.GetCci2Orb(), childCelestial.Orbit.Orb2ParentCci) + .Inverse(); + var newPosition = (posCci - childPos).Transform(rotation); + var newVelocity = (orb.GetVelocityCciAt(simTime) - childCelestial.GetVelocityCci(simTime)).Transform(rotation); + orb = Orbit.CreateFromStateCci(childCelestial, simTime, newPosition, newVelocity, orb.OrbitLineColor); + } + + // Go to the specified time and set the vehicle's orbit to the ephemeris orbit at that time + // (this even works backwards in time, thanks to the patch in UniversePatch!) + var dt = simTime.Seconds() - Universe.GetElapsedSeconds(); Universe.CompleteAndApplyPreviousOrbitSolvers(); Universe.ResetSimulationSpeed(); Universe.ExecuteNextOrbitSolvers(dt); -- 2.51.2