StarSim

StarSim.git
git clone git://git.lenczewski.org/StarSim.git
Log | Files | Refs | README | LICENSE

commit fb6cfa4db988de2cfa8b247ae59457418fb139ec
parent 41fc6f39d7b79bef1375d0e5af80488fd3814ef3
Author: Mikolaj Lenczewski <33129490+EnderRifter@users.noreply.github.com>
Date:   Wed, 19 Jun 2019 18:30:38 +0100

Orbits are now possible.

Diffstat:
MStarSim/StarSim/Program.cs | 158++++++++++++++++++++++++++++++++++++++++----------------------------------------
MStarSim/StarSimLib/Body.cs | 108++++++++++++++++++++++++++++++++++---------------------------------------------
MStarSim/StarSimLib/Constants.cs | 29+++++++++++++++++------------
DStarSim/StarSimLib/ExampleBody.cs | 69---------------------------------------------------------------------
AStarSim/StarSimLib/Examples/ExampleBody.cs | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MStarSim/StarSimLib/OrbitGenerator.cs | 43+++++++++++++++++++++++++------------------
MStarSim/StarSimLib/StarSimLib.csproj | 6+++---
MStarSim/StarSimLib/Vector3d.cs | 149++++++++++++++++++++++++++++++++++++++++---------------------------------------
8 files changed, 315 insertions(+), 316 deletions(-)

diff --git a/StarSim/StarSim/Program.cs b/StarSim/StarSim/Program.cs @@ -16,15 +16,15 @@ namespace StarSim private static readonly Random RNG = new Random(); /// <summary> - /// The current generation of <see cref="Body"/>s that we have. Increments each time the bodies are regenerated - /// via <see cref="GenerateBodies(int, bool)"/>. + /// Holds all the <see cref="Body"/> instances that should be simulated. /// </summary> - private static uint _generation; + private static Body[] _bodies; /// <summary> - /// Holds all the <see cref="Body"/> instances that should be simulated. + /// The current generation of <see cref="Body"/>s that we have. Increments each time the bodies are regenerated + /// via <see cref="GenerateBodies(int, bool)"/>. /// </summary> - private static Body[] _bodies; + private static uint _generation; /// <summary> /// Maps a <see cref="Body"/> to the <see cref="CircleShape"/> that represents it, and is drawn to the @@ -32,36 +32,29 @@ namespace StarSim /// </summary> private static Dictionary<Body, CircleShape> BodyShapeMap; - private static void Main(string[] args) + /// <summary> + /// Draws each <see cref="Body"/> in the given <see cref="IEnumerable{T}"/> to the given window. + /// </summary> + /// <param name="bodies">The collection of <see cref="Body"/>s to draw.</param> + /// <param name="renderTarget">The target to draw the <see cref="Body"/>s to.</param> + /// <param name="originOffset"> + /// The offset that has to be applied to the positions of the <see cref="CircleShape"/>, so that they appear + /// to be in the centre of the screen and not the top left corner. + /// </param> + private static void DrawBodies(IEnumerable<Body> bodies, RenderWindow renderTarget, Vector2u originOffset) { - Console.WriteLine("Hello World!"); - - GenerateBodies(10, true); - - Console.ReadLine(); - - RenderWindow window = new RenderWindow(VideoMode.DesktopMode, "N-Body Simulator", Styles.Default); - window.SetFramerateLimit(Constants.FrameRate); - window.Closed += (sender, eventArgs) => ((RenderWindow)sender).Close(); - window.KeyPressed += HandleKeyPressed; - - // caches the delta between the screen origin (top left corner) and the world origin, - // which should be the centre of the screen - uint wx = window.Size.X, wy = window.Size.Y; - uint dx = wx / 2, dy = wy / 2; - Vector2u originOffset = new Vector2u(dx, dy); - - DrawBodies(_bodies, window, originOffset); - - while (window.IsOpen) + foreach (Body body in bodies) { - window.Clear(); - window.DispatchEvents(); + // get the cached shape and projects the current bodies 3D position down to a 2D position, + // which is used as the new position of the shape. + CircleShape shape = BodyShapeMap[body]; - UpdateBodiesBruteForce(_bodies, Constants.TimeStep); - DrawBodies(_bodies, window, originOffset); + shape.Position = new Vector2f( + (float)(body.Position.X * Constants.UniverseScalingFactor + originOffset.X), + (float)(body.Position.Y * Constants.UniverseScalingFactor + originOffset.Y) + ); - window.Display(); + shape.Draw(renderTarget, RenderStates.Default); } } @@ -79,7 +72,7 @@ namespace StarSim float mass = (float)(RNG.NextDouble() * Constants.SolarMass); Vector3d position = OrbitGenerator.RandomPosition(); - Vector3d velocity = new Vector3d(); //OrbitGenerator.RandomOrbit(position); + Vector3d velocity = OrbitGenerator.RandomOrbit(position); //new Vector3d(); _bodies[i] = new Body(position, velocity, mass, _generation, id); BodyShapeMap.Add(_bodies[i], new CircleShape(4) { FillColor = Color.White }); @@ -97,74 +90,81 @@ namespace StarSim } /// <summary> - /// Updates the positions of all the given <see cref="Body"/>s with O(n^2) time complexity, with the given time step. + /// Handles key presses. /// </summary> - /// <param name="bodies">The collection of <see cref="Body"/>s whose positions to update.</param> - /// <param name="deltaTime">The time step.</param> - private static void UpdateBodiesBruteForce(IEnumerable<Body> bodies, double deltaTime) + /// <param name="sender">The <see cref="RenderWindow"/> that sent the event.</param> + /// <param name="eventArgs">The <see cref="KeyEventArgs"/> about the key press.</param> + private static void HandleKeyPressed(object sender, KeyEventArgs eventArgs) { - IEnumerable<Body> bodyEnumerable = bodies as Body[] ?? bodies.ToArray(); - Vector3d forceVector = new Vector3d(); - - foreach (Body body in bodyEnumerable) + switch (eventArgs.Code) { - // resets the force vector to avoid another instantiation and allocation - forceVector.X = 0; - forceVector.Y = 0; - forceVector.Z = 0; + case Keyboard.Key.Space: + UpdateBodiesBruteForce(_bodies, Constants.TimeStep); + break; - // use LINQ expression as it is more concise; sum attraction vectors for all other bodies - forceVector = bodyEnumerable.Where(b => b != body).Aggregate(forceVector, (current, b) => current + Body.GetForceBetween(body, b)); + case Keyboard.Key.G: + GenerateBodies(10, true); + break; - body.Update(forceVector, deltaTime); + default: + break; } } - /// <summary> - /// Draws each <see cref="Body"/> in the given <see cref="IEnumerable{T}"/> to the given window. - /// </summary> - /// <param name="bodies">The collection of <see cref="Body"/>s to draw.</param> - /// <param name="renderTarget">The target to draw the <see cref="Body"/>s to.</param> - /// <param name="originOffset"> - /// The offset that has to be applied to the positions of the <see cref="CircleShape"/>, so that they appear - /// to be in the centre of the screen and not the top left corner. - /// </param> - private static void DrawBodies(IEnumerable<Body> bodies, RenderWindow renderTarget, Vector2u originOffset) + private static void Main(string[] args) { - foreach (Body body in bodies) + Console.WriteLine("Hello World!"); + + GenerateBodies(Constants.BodyCount, true); + + Console.ReadLine(); + + RenderWindow window = new RenderWindow(VideoMode.DesktopMode, "N-Body Simulator", Styles.Default); + window.SetFramerateLimit(Constants.FrameRate); + window.Closed += (sender, eventArgs) => ((RenderWindow)sender).Close(); + window.KeyPressed += HandleKeyPressed; + + // caches the delta between the screen origin (top left corner) and the world origin, + // which should be the centre of the screen + uint wx = window.Size.X, wy = window.Size.Y; + uint dx = wx / 2, dy = wy / 2; + Vector2u originOffset = new Vector2u(dx, dy); + + DrawBodies(_bodies, window, originOffset); + + while (window.IsOpen) { - // get the cached shape and projects the current bodies 3D position down to a 2D position, - // which is used as the new position of the shape. - CircleShape shape = BodyShapeMap[body]; + window.Clear(); + window.DispatchEvents(); - shape.Position = new Vector2f( - (float)(body.Position.X * Constants.UniverseScalingFactor + originOffset.X), - (float)(body.Position.Y * Constants.UniverseScalingFactor + originOffset.Y) - ); + UpdateBodiesBruteForce(_bodies, Constants.TimeStep); + DrawBodies(_bodies, window, originOffset); - shape.Draw(renderTarget, RenderStates.Default); + window.Display(); } } /// <summary> - /// Handles key presses. + /// Updates the positions of all the given <see cref="Body"/>s with O(n^2) time complexity, with the given time step. /// </summary> - /// <param name="sender">The <see cref="RenderWindow"/> that sent the event.</param> - /// <param name="eventArgs">The <see cref="KeyEventArgs"/> about the key press.</param> - private static void HandleKeyPressed(object sender, KeyEventArgs eventArgs) + /// <param name="bodies">The collection of <see cref="Body"/>s whose positions to update.</param> + /// <param name="deltaTime">The time step.</param> + private static void UpdateBodiesBruteForce(IEnumerable<Body> bodies, double deltaTime) { - switch (eventArgs.Code) + IEnumerable<Body> bodyEnumerable = bodies as Body[] ?? bodies.ToArray(); + Vector3d forceVector = new Vector3d(); + + foreach (Body body in bodyEnumerable) { - case Keyboard.Key.Space: - UpdateBodiesBruteForce(_bodies, Constants.TimeStep); - break; + // resets the force vector to avoid another instantiation and allocation + forceVector.X = 0; + forceVector.Y = 0; + forceVector.Z = 0; - case Keyboard.Key.G: - GenerateBodies(10, true); - break; + // use LINQ expression as it is more concise; sum attraction vectors for all other bodies + forceVector = bodyEnumerable.Where(b => b != body).Aggregate(forceVector, (current, b) => current + Body.GetForceBetween(body, b)); - default: - break; + body.Update(forceVector, deltaTime); } } } diff --git a/StarSim/StarSimLib/Body.cs b/StarSim/StarSimLib/Body.cs @@ -9,8 +9,6 @@ namespace StarSimLib /// </summary> public class Body { - #region Variables - /// <summary> /// Describes how the <see cref="Body"/> instance should be formatted as a <see cref="string"/>. /// </summary> @@ -27,29 +25,6 @@ namespace StarSimLib /// </summary> public readonly uint Id; - #endregion Variables - - #region Properties - - /// <summary> - /// The current position of the <see cref="Body"/> in 3D space. - /// </summary> - public Vector3d Position { get; private set; } - - /// <summary> - /// The current velocity of the <see cref="Body"/> in 3D space. - /// </summary> - public Vector3d Velocity { get; private set; } - - /// <summary> - /// The mass of the <see cref="Body"/>. - /// </summary> - public double Mass { get; private set; } - - #endregion Properties - - #region Constructors - /// <summary> /// Initialises a new instance of the <see cref="Body"/> class. /// </summary> @@ -68,48 +43,20 @@ namespace StarSimLib Mass = mass; } - #endregion Constructors - - #region Methods - - #region Overrides of Object - - /// <inheritdoc /> - public override string ToString() - { - return string.Format(BodyFormatString, Generation, Id, Position.X, Position.Y, Position.Z, Velocity.X, Velocity.Y, Velocity.Z, Mass); - } - - #endregion Overrides of Object - /// <summary> - /// Updates the <see cref="Position"/> of the current body using the given force vector and time step. + /// The mass of the <see cref="Body"/>. /// </summary> - /// <param name="forceVector">The sum vector of all forces due to other <see cref="Body"/>s.</param> - /// <param name="deltaTime">The time step.</param> - public void Update(Vector3d forceVector, double deltaTime) - { - Velocity += deltaTime * forceVector / Mass; - Position += deltaTime * Velocity; - } + public double Mass { get; private set; } /// <summary> - /// Finds and returns the distance between the current <see cref="Body"/> instance and the given <see cref="Body"/>. - /// In other words, it finds the magnitude of the translation vector between the two <see cref="Body"/> instances. + /// The current position of the <see cref="Body"/> in 3D space. /// </summary> - /// <param name="body">The other <see cref="Body"/> instance to which to calculate the distance.</param> - /// <param name="displacement">The vector showing the displacement of the current body from the given one.</param> - /// <returns>The distance to the other <see cref="Body"/> as a <see cref="float"/>.</returns> - public double DistanceTo(Body body, out Vector3d displacement) - { - double dpx = body.Position.X - Position.X, - dpy = body.Position.Y - Position.Y, - dpz = body.Position.Z - Position.Z; - - displacement = new Vector3d(dpx, dpy, dpz); + public Vector3d Position { get; private set; } - return Math.Sqrt(dpx * dpx + dpy * dpy + dpz * dpz); - } + /// <summary> + /// The current velocity of the <see cref="Body"/> in 3D space. + /// </summary> + public Vector3d Velocity { get; private set; } /// <summary> /// Gets the force vector for the attraction between <see cref="Body"/> A and <see cref="Body"/> B. @@ -139,6 +86,43 @@ namespace StarSimLib return new Vector3d(force * dx / distance, force * dy / distance, force * dz / distance); } - #endregion Methods + /// <summary> + /// Finds and returns the distance between the current <see cref="Body"/> instance and the given <see cref="Body"/>. + /// In other words, it finds the magnitude of the translation vector between the two <see cref="Body"/> instances. + /// </summary> + /// <param name="body">The other <see cref="Body"/> instance to which to calculate the distance.</param> + /// <param name="displacement">The vector showing the displacement of the current body from the given one.</param> + /// <returns>The distance to the other <see cref="Body"/> as a <see cref="float"/>.</returns> + public double DistanceTo(Body body, out Vector3d displacement) + { + double dpx = body.Position.X - Position.X, + dpy = body.Position.Y - Position.Y, + dpz = body.Position.Z - Position.Z; + + displacement = new Vector3d(dpx, dpy, dpz); + + return Math.Sqrt(dpx * dpx + dpy * dpy + dpz * dpz); + } + + /// <summary> + /// Updates the <see cref="Position"/> of the current body using the given force vector and time step. + /// </summary> + /// <param name="forceVector">The sum vector of all forces due to other <see cref="Body"/>s.</param> + /// <param name="deltaTime">The time step.</param> + public void Update(Vector3d forceVector, double deltaTime) + { + Velocity += deltaTime * forceVector / Mass; + Position += deltaTime * Velocity; + } + + #region Overrides of Object + + /// <inheritdoc /> + public override string ToString() + { + return string.Format(BodyFormatString, Generation, Id, Position.X, Position.Y, Position.Z, Velocity.X, Velocity.Y, Velocity.Z, Mass); + } + + #endregion Overrides of Object } } \ No newline at end of file diff --git a/StarSim/StarSimLib/Constants.cs b/StarSim/StarSimLib/Constants.cs @@ -8,19 +8,19 @@ namespace StarSimLib public static class Constants { /// <summary> - /// The frame rate limit for the simulation. + /// The amount of bodies that are rendered by default. /// </summary> - public const uint FrameRate = 60; + public const int BodyCount = 20; /// <summary> - /// The number of seconds that each frame represents. + /// The mass of the central body, if it is included. /// </summary> - public const double SecondsPerFrame = 1e7f; + public const double CentralBodyMass = SolarMass * 1e6; /// <summary> - /// The default time step for the simulation. + /// The frame rate limit for the simulation. /// </summary> - public const double TimeStep = SecondsPerFrame * FrameRate; + public const uint FrameRate = 60; /// <summary> /// The gravitational constant (m^3 kg^-1 s^-2). @@ -28,9 +28,9 @@ namespace StarSimLib public const double G = 6.673e-11f; /// <summary> - /// The mass of the sun (1.98892e30f). + /// The number of seconds that each frame represents. /// </summary> - public const double SolarMass = 1.98892e30f; + public const double SecondsPerFrame = 1e8f; /// <summary> /// Softens the force between <see cref="Body"/>s to avoid infinities. @@ -43,9 +43,14 @@ namespace StarSimLib public const double SofteningFactor2 = SofteningFactor * SofteningFactor; /// <summary> - /// The maximum radius within which <see cref="Body"/>s will be placed (1e18f). + /// The mass of the sun (1.98892e30f). /// </summary> - public const double UniverseSize = 1e18f; + public const double SolarMass = 1.98892e30f; + + /// <summary> + /// The default time step for the simulation. + /// </summary> + public const double TimeStep = SecondsPerFrame * FrameRate; /// <summary> /// Factor by which to multiply the position of <see cref="Body"/>s to scale them to the screen for displaying. @@ -53,8 +58,8 @@ namespace StarSimLib public const double UniverseScalingFactor = 2500 / UniverseSize; /// <summary> - /// The mass of the central body, if it is included. + /// The maximum radius within which <see cref="Body"/>s will be placed (1e18f). /// </summary> - public const double CentralBodyMass = SolarMass * 1e6f; + public const double UniverseSize = 1e18f; } } \ No newline at end of file diff --git a/StarSim/StarSimLib/ExampleBody.cs b/StarSim/StarSimLib/ExampleBody.cs @@ -1,68 +0,0 @@ -using System; - -namespace StarSimLib -{ - public class ExampleBody - { - private static readonly double G = 6.673e-11; // gravitational constant - private static readonly double solarmass = 1.98892e30; - - public double pos_x, pos_y; - public double vel_x, vel_y; - public double force_x, force_y; - public double mass; - - public ExampleBody(double px, double py, double vx, double vy, double mass) - { - pos_x = px; - pos_y = py; - vel_x = vx; - vel_y = vy; - this.mass = mass; - } - - public void update(double delta_time) - { - vel_x += delta_time * force_x / mass; - vel_y += delta_time * force_y / mass; - pos_x += delta_time * vel_x; - pos_y += delta_time * vel_y; - } - - public double distanceTo(ExampleBody b) - { - double dx = pos_x - b.pos_x; - double dy = pos_y - b.pos_y; - return Math.Sqrt(dx * dx + dy * dy); - } - - public void resetForce() - { - force_x = 0.0; - force_y = 0.0; - } - - public void addForce(ExampleBody b) - { - ExampleBody a = this; - double softening_factor = 3E4; - double dx = b.pos_x - a.pos_x; - double dy = b.pos_y - a.pos_y; - double dist = Math.Sqrt(dx * dx + dy * dy); - double force = (G * a.mass * b.mass) / (dist * dist + softening_factor * softening_factor); - - a.force_x += force * dx / dist; - a.force_y += force * dy / dist; - } - - #region Overrides of Object - - /// <inheritdoc /> - public override string ToString() - { - return $"Body @ ({pos_x}, {pos_y}) with velocity ({vel_x}, {vel_y})"; - } - - #endregion Overrides of Object - } -} -\ No newline at end of file diff --git a/StarSim/StarSimLib/Examples/ExampleBody.cs b/StarSim/StarSimLib/Examples/ExampleBody.cs @@ -0,0 +1,68 @@ +using System; + +namespace StarSimLib.Examples +{ + public class ExampleBody + { + private static readonly double G = 6.673e-11; // gravitational constant + private static readonly double solarmass = 1.98892e30; + + public double force_x, force_y; + public double mass; + public double pos_x, pos_y; + public double vel_x, vel_y; + + public ExampleBody(double px, double py, double vx, double vy, double mass) + { + pos_x = px; + pos_y = py; + vel_x = vx; + vel_y = vy; + this.mass = mass; + } + + public void addForce(ExampleBody b) + { + ExampleBody a = this; + double softening_factor = 3E4; + double dx = b.pos_x - a.pos_x; + double dy = b.pos_y - a.pos_y; + double dist = Math.Sqrt(dx * dx + dy * dy); + double force = (G * a.mass * b.mass) / (dist * dist + softening_factor * softening_factor); + + a.force_x += force * dx / dist; + a.force_y += force * dy / dist; + } + + public double distanceTo(ExampleBody b) + { + double dx = pos_x - b.pos_x; + double dy = pos_y - b.pos_y; + return Math.Sqrt(dx * dx + dy * dy); + } + + public void resetForce() + { + force_x = 0.0; + force_y = 0.0; + } + + public void update(double delta_time) + { + vel_x += delta_time * force_x / mass; + vel_y += delta_time * force_y / mass; + pos_x += delta_time * vel_x; + pos_y += delta_time * vel_y; + } + + #region Overrides of Object + + /// <inheritdoc /> + public override string ToString() + { + return $"Body @ ({pos_x}, {pos_y}) with velocity ({vel_x}, {vel_y})"; + } + + #endregion Overrides of Object + } +} +\ No newline at end of file diff --git a/StarSim/StarSimLib/OrbitGenerator.cs b/StarSim/StarSimLib/OrbitGenerator.cs @@ -15,20 +15,6 @@ namespace StarSimLib private static readonly Random Rng = new Random(); /// <summary> - /// Returns a random position within the universe sphere (see <see cref="Constants.UniverseSize"/>). - /// </summary> - /// <returns>A 3D position vector.</returns> - public static Vector3d RandomPosition() - { - double RandomPos() - { - return Constants.UniverseSize * Math.Exp(-1.8) * (.5 - Rng.NextDouble()); - } - - return new Vector3d(RandomPos(), RandomPos(), RandomPos()); - } - - /// <summary> /// Returns a randomised orbit around a central, heavy mass. /// </summary> /// <param name="positionVector">The position vector for the body for which to generate the orbit.</param> @@ -38,20 +24,41 @@ namespace StarSimLib Vector3d position = positionVector; // F = G m1 - m2 / distance - double distanceToCentralBody = positionVector.Magnitude(); - double numerator = Constants.G * Constants.SolarMass; + double distanceToCentralBody = position.Magnitude(); + double numerator = Constants.G * Constants.CentralBodyMass; double velocityMagnitude = Math.Sqrt(numerator / distanceToCentralBody); double absAngle = Math.Atan(Math.Abs(position.X / position.Y)); double velocityTheta = Math.PI / 2 - absAngle; double velocityPhi = Rng.NextDouble() * Math.PI; + double vertical = Math.Min(2e8 / distanceToCentralBody, 2e4); + double vx = -1 * Math.Sign(position.Y) * Math.Cos(velocityTheta) * velocityMagnitude; - double vy = Math.Sign(position.X) * Math.Sin(velocityTheta) * velocityMagnitude; - double vz = 0; + double vy = (Rng.NextDouble() - 0.5) * vertical; + double vz = Math.Sign(position.X) * Math.Sin(velocityTheta) * velocityMagnitude; + + // TODO: Implement 3d velocities and rendering + // mapping of the 3d values to 2d values + vy = vz; + vz = 0; // Randomly orient the orbit return !(Rng.NextDouble() <= 0.5f) ? new Vector3d(vx, vy, vz) : new Vector3d(-vx, -vy, -vz); } + + /// <summary> + /// Returns a random position within the universe sphere (see <see cref="Constants.UniverseSize"/>). + /// </summary> + /// <returns>A 3D position vector.</returns> + public static Vector3d RandomPosition() + { + double RandomPos() + { + return Constants.UniverseSize * Math.Exp(-1.8) * (.5 - Rng.NextDouble()); + } + + return new Vector3d(RandomPos(), RandomPos(), RandomPos()); + } } } \ No newline at end of file diff --git a/StarSim/StarSimLib/StarSimLib.csproj b/StarSim/StarSimLib/StarSimLib.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netstandard2.0</TargetFramework> @@ -7,5 +7,4 @@ <ItemGroup> <PackageReference Include="SFML.Net" Version="2.5.0" /> </ItemGroup> - -</Project> +</Project> +\ No newline at end of file diff --git a/StarSim/StarSimLib/Vector3d.cs b/StarSim/StarSimLib/Vector3d.cs @@ -1,5 +1,6 @@ using System; using System.Data.Common; +using System.Diagnostics.Contracts; using System.Transactions; namespace StarSimLib @@ -52,69 +53,6 @@ namespace StarSimLib #region Operator Overloads /// <summary> - /// Implements the addition operator for 2 <see cref="Vector3d"/>s. - /// </summary> - /// <param name="vector">The original <see cref="Vector3d"/>.</param> - /// <param name="vector2">The other <see cref="Vector3d"/>.</param> - /// <returns>The new <see cref="Vector3d"/>.</returns> - public static Vector3d operator +(Vector3d vector, Vector3d vector2) - { - vector.X += vector2.X; - vector.Y += vector2.Y; - vector.Z += vector2.Z; - - return vector; - } - - /// <summary> - /// Implements the addition operator for a <see cref="Vector3d"/> and a (X, Y, Z) tuple. - /// </summary> - /// <param name="vector">The original <see cref="Vector3d"/>.</param> - /// <param name="vector2">The 3D tuple.</param> - /// <returns>The new <see cref="Vector3d"/>.</returns> - public static Vector3d operator +(Vector3d vector, (double X, double Y, double Z) vector2) - { - (double x, double y, double z) = vector2; - - vector.X += x; - vector.Y += y; - vector.Z += z; - - return vector; - } - - /// <summary> - /// Implements the addition operator for a <see cref="Vector3d"/> and a (X, Y, Z) tuple. - /// </summary> - /// <param name="vector">The original <see cref="Vector3d"/>.</param> - /// <param name="vector2">The 3D tuple.</param> - /// <returns>The new <see cref="Vector3d"/>.</returns> - public static Vector3d operator +((double X, double Y, double Z) vector2, Vector3d vector) => vector + vector2; - - /// <summary> - /// Implements the addition operator for a <see cref="Vector3d"/> and a scalar <see cref="double"/> value. - /// </summary> - /// <param name="vector">The original <see cref="Vector3d"/>.</param> - /// <param name="scalar">The scalar <see cref="double"/>.</param> - /// <returns>The new <see cref="Vector3d"/>.</returns> - public static Vector3d operator +(Vector3d vector, double scalar) - { - vector.X += scalar; - vector.Y += scalar; - vector.Z += scalar; - - return vector; - } - - /// <summary> - /// Implements the addition operator for a <see cref="Vector3d"/> and a scalar <see cref="double"/> value. - /// </summary> - /// <param name="vector">The original <see cref="Vector3d"/>.</param> - /// <param name="scalar">The scalar <see cref="double"/>.</param> - /// <returns>The new <see cref="Vector3d"/>.</returns> - public static Vector3d operator +(double scalar, Vector3d vector) => vector + scalar; - - /// <summary> /// Implements the subtraction operator for 2 <see cref="Vector3d"/>s. /// </summary> /// <param name="vector">The original <see cref="Vector3d"/>.</param> @@ -303,12 +241,76 @@ namespace StarSimLib /// <returns>The new <see cref="Vector3d"/>.</returns> public static Vector3d operator /(double scalar, Vector3d vector) => vector / scalar; + /// <summary> + /// Implements the addition operator for 2 <see cref="Vector3d"/>s. + /// </summary> + /// <param name="vector">The original <see cref="Vector3d"/>.</param> + /// <param name="vector2">The other <see cref="Vector3d"/>.</param> + /// <returns>The new <see cref="Vector3d"/>.</returns> + public static Vector3d operator +(Vector3d vector, Vector3d vector2) + { + vector.X += vector2.X; + vector.Y += vector2.Y; + vector.Z += vector2.Z; + + return vector; + } + + /// <summary> + /// Implements the addition operator for a <see cref="Vector3d"/> and a (X, Y, Z) tuple. + /// </summary> + /// <param name="vector">The original <see cref="Vector3d"/>.</param> + /// <param name="vector2">The 3D tuple.</param> + /// <returns>The new <see cref="Vector3d"/>.</returns> + public static Vector3d operator +(Vector3d vector, (double X, double Y, double Z) vector2) + { + (double x, double y, double z) = vector2; + + vector.X += x; + vector.Y += y; + vector.Z += z; + + return vector; + } + + /// <summary> + /// Implements the addition operator for a <see cref="Vector3d"/> and a (X, Y, Z) tuple. + /// </summary> + /// <param name="vector">The original <see cref="Vector3d"/>.</param> + /// <param name="vector2">The 3D tuple.</param> + /// <returns>The new <see cref="Vector3d"/>.</returns> + public static Vector3d operator +((double X, double Y, double Z) vector2, Vector3d vector) => vector + vector2; + + /// <summary> + /// Implements the addition operator for a <see cref="Vector3d"/> and a scalar <see cref="double"/> value. + /// </summary> + /// <param name="vector">The original <see cref="Vector3d"/>.</param> + /// <param name="scalar">The scalar <see cref="double"/>.</param> + /// <returns>The new <see cref="Vector3d"/>.</returns> + public static Vector3d operator +(Vector3d vector, double scalar) + { + vector.X += scalar; + vector.Y += scalar; + vector.Z += scalar; + + return vector; + } + + /// <summary> + /// Implements the addition operator for a <see cref="Vector3d"/> and a scalar <see cref="double"/> value. + /// </summary> + /// <param name="vector">The original <see cref="Vector3d"/>.</param> + /// <param name="scalar">The scalar <see cref="double"/>.</param> + /// <returns>The new <see cref="Vector3d"/>.</returns> + public static Vector3d operator +(double scalar, Vector3d vector) => vector + scalar; + #endregion Operator Overloads /// <summary> /// Returns the absolute value of this <see cref="Vector3d"/>. /// </summary> /// <returns>The absolute value (magnitude) of this <see cref="Vector3d"/>, as a <see cref="double"/>.</returns> + [Pure] public double Abs() { return Math.Sqrt(X * X + Y * Y + Z * Z); @@ -318,6 +320,7 @@ namespace StarSimLib /// Returns the magnitude of this <see cref="Vector3d"/>. /// </summary> /// <returns>The magnitude (absolute value) of this <see cref="Vector3d"/>, as a <see cref="double"/>.</returns> + [Pure] public double Magnitude() { return Abs(); @@ -329,14 +332,14 @@ namespace StarSimLib public static class UnitVectors { /// <summary> - /// The positive unit vector for the X axis. + /// The negative unit vector for the Z axis. /// </summary> - public static readonly Vector3d Left = new Vector3d(1, 0, 0); + public static readonly Vector3d Backwards = new Vector3d(0, 0, -1); /// <summary> - /// The positive unit vector for the Y axis. + /// The negative unit vector for the Y axis. /// </summary> - public static readonly Vector3d Up = new Vector3d(0, 1, 0); + public static readonly Vector3d Down = new Vector3d(0, -1, 0); /// <summary> /// The positive unit vector for the Z axis. @@ -344,19 +347,19 @@ namespace StarSimLib public static readonly Vector3d Forwards = new Vector3d(0, 0, 1); /// <summary> - /// The negative unit vector for the X axis. + /// The positive unit vector for the X axis. /// </summary> - public static readonly Vector3d Right = new Vector3d(-1, 0, 0); + public static readonly Vector3d Left = new Vector3d(1, 0, 0); /// <summary> - /// The negative unit vector for the Y axis. + /// The negative unit vector for the X axis. /// </summary> - public static readonly Vector3d Down = new Vector3d(0, -1, 0); + public static readonly Vector3d Right = new Vector3d(-1, 0, 0); /// <summary> - /// The negative unit vector for the Z axis. + /// The positive unit vector for the Y axis. /// </summary> - public static readonly Vector3d Backwards = new Vector3d(0, 0, -1); + public static readonly Vector3d Up = new Vector3d(0, 1, 0); } } } \ No newline at end of file