diff --git a/scripts/orbits/Orbit.cs b/scripts/orbits/Orbit.cs new file mode 100644 index 0000000..0aca13e --- /dev/null +++ b/scripts/orbits/Orbit.cs @@ -0,0 +1,12 @@ +using Godot; +using System; + +public class Orbit +{ + public Orbit(PointMass a, PointMass b) + { + + } + + // ellipse +} diff --git a/scripts/orbits/OrbitSystem.cs b/scripts/orbits/OrbitSystem.cs index 358ad53..61a432a 100644 --- a/scripts/orbits/OrbitSystem.cs +++ b/scripts/orbits/OrbitSystem.cs @@ -26,7 +26,9 @@ public class OrbitSystem : Node, IMassive, ILocation public float Mass { get; } = 1; - private ImmediateGeometry _orbit; + private Orbit _orbit; + + private ImmediateGeometry _orbitGeometry; public override void _Ready() { @@ -39,35 +41,45 @@ public class OrbitSystem : Node, IMassive, ILocation DrawOrbit(); } + private void InitOrbit() + { + + } + private void DrawOrbit() { int steps = 100; - _orbit.Clear(); - _orbit.Begin(Mesh.PrimitiveType.LineLoop); - _orbit.SetColor(new Color(1, 0, 0)); + _orbitGeometry.Clear(); + _orbitGeometry.Begin(Mesh.PrimitiveType.LineLoop); + _orbitGeometry.SetColor(new Color(1, 0, 0)); + + var ellipse = new Ellipse(1, .5); + for (int i = 0; i < steps; i++) { float t = i / (float)steps; float a = t * Mathf.Tau; - _orbit.AddVertex(new Vector3 + var v2 = ellipse.Focus0 + ellipse.GetPosition(a); + + _orbitGeometry.AddVertex(new Vector3 { - x = Mathf.Sin(a), - z = Mathf.Cos(a) + x = (float)v2.X, + z = (float)v2.Y }); } - _orbit.End(); + _orbitGeometry.End(); } private void InitGeometry() { - _orbit = new ImmediateGeometry(); + _orbitGeometry = new ImmediateGeometry(); var m = new SpatialMaterial(); m.VertexColorUseAsAlbedo = true; m.FlagsUnshaded = true; - _orbit.MaterialOverride = m; - AddChild(_orbit); + _orbitGeometry.MaterialOverride = m; + AddChild(_orbitGeometry); } private void InitPointMasses() diff --git a/scripts/orbits/Planet.cs b/scripts/orbits/Planet.cs index c93a33a..877455f 100644 --- a/scripts/orbits/Planet.cs +++ b/scripts/orbits/Planet.cs @@ -1,7 +1,7 @@ using Godot; using System; -public class Planet : Node +public class Planet : Node, IMassive { [Export] public float Mass { get; set; } diff --git a/scripts/orbits/PointMass.cs b/scripts/orbits/PointMass.cs index bb277c1..bbeaa14 100644 --- a/scripts/orbits/PointMass.cs +++ b/scripts/orbits/PointMass.cs @@ -1,6 +1,6 @@ using Godot; -struct PointMass : IMassive, ILocation +public struct PointMass : IMassive, ILocation { public float Mass => _massive == null ? _mass : _massive.Mass; public Vector3 Position => _spatial.Translation; diff --git a/scripts/orbits/math/Ellipse.cs b/scripts/orbits/math/Ellipse.cs new file mode 100644 index 0000000..e1fff2e --- /dev/null +++ b/scripts/orbits/math/Ellipse.cs @@ -0,0 +1,63 @@ +using Godot; +using System; +using Vim.Math3d; + +public struct Ellipse +{ + public Ellipse(double a = 1, double e = 0) + { + SemiMajorAxis = a; + Eccentricity = e; + + // TODO: this is an immutable struct, so initialise everything else + // in the constructor to avoid recalculating properties whenever + // they are accessed + } + + /// + /// Semi-major axis + /// + public double a => SemiMajorAxis; + public double SemiMajorAxis { get; } + + /// + /// Eccentricity + /// + public double e => Eccentricity; + public double Eccentricity { get; } + + /// + /// Semi-minor axis + /// + public double b => SemiMinorAxis; + public double SemiMinorAxis => Math.Sqrt(Apisides.max * Apisides.min); + + /// + /// Get a position on the auxiliary circle + /// + /// Angle in radians around the circle + /// 2D position on the circle scaled by the semi-major axis + public DVector2 GetAuxiliaryPosition2D(double t = 0) => + new DVector2(Math.Cos(t), Math.Sin(t)) * a; + + private Apisides Apisides => new Apisides(a, e); + + public DVector2 GetPosition(double t) => + new DVector2(Math.Cos(t) * a, Math.Sin(t) * b); + + public DVector2 Focus0 => new DVector2(-GetFocusDistance(), 0); + public DVector2 Focus1 => new DVector2(GetFocusDistance(), 0); + private double GetFocusDistance() => Math.Sqrt(a * a - b * b); +} + +public struct Apisides +{ + public readonly double min; + public readonly double max; + + public Apisides(double a, double e) + { + min = a * (1 - e); + max = a * (1 + e); + } +} \ No newline at end of file