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