commit af469d3e1a376b7c0ee5ea8d810d42bc38447fb1
parent bbd69cc229eba112300e33359d91f9cd01b3e3b6
Author: Mikolaj Lenczewski <33129490+EnderRifter@users.noreply.github.com>
Date: Mon, 8 Jul 2019 11:22:20 +0100
Initial fix for barnes-hut bug
Diffstat:
7 files changed, 311 insertions(+), 69 deletions(-)
diff --git a/StarSim/StarSim/Program.cs b/StarSim/StarSim/Program.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading;
using SFML.Graphics;
using SFML.Window;
using StarSimLib;
@@ -103,6 +104,8 @@ namespace StarSim
bodyDrawer.DrawBodies();
+ ulong frameCounter = 0;
+
while (window.IsOpen)
{
window.Clear();
@@ -111,11 +114,14 @@ namespace StarSim
if (!inputHandler.IsSimulationPaused)
{
bodyPositionUpdater(bodies, Constants.TimeStep);
+ Console.WriteLine($"Finished physics frame: {frameCounter++}");
}
bodyDrawer.DrawBodies();
window.Display();
+
+ //Console.Read();
}
Console.WriteLine("Goodbye, World!");
diff --git a/StarSim/StarSimLib/Constants.cs b/StarSim/StarSimLib/Constants.cs
@@ -1,4 +1,7 @@
-using StarSimLib.Data_Structures;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using StarSimLib.Data_Structures;
namespace StarSimLib
{
@@ -10,7 +13,7 @@ namespace StarSimLib
/// <summary>
/// The amount of bodies that are rendered by default.
/// </summary>
- public const int BodyCount = 2;
+ public const int BodyCount = 10;
/// <summary>
/// The mass of the central body, if it is included.
@@ -33,6 +36,12 @@ namespace StarSimLib
public const double G = 6.673e-11f;
/// <summary>
+ /// The minimum width of a tree. Subtrees are not created when if their width would be smaller than this value,
+ /// to prevent widths of NaN as a result of division errors.
+ /// </summary>
+ public const double MinimumTreeWidth = 1;
+
+ /// <summary>
/// The number of seconds that each simulation tick represents.
/// </summary>
public const double SecondsPerTick = 1e8f;
@@ -45,7 +54,7 @@ namespace StarSimLib
/// <summary>
/// Softens the force between <see cref="Body"/>s to avoid infinities.
/// </summary>
- public const double SofteningFactor = 3e4f;
+ public const double SofteningFactor = 700;
/// <summary>
/// The square of the <see cref="SofteningFactor"/>.
@@ -68,9 +77,8 @@ namespace StarSimLib
public const double TimeStep = SecondsPerTick * (SimulationRate / (float)FrameRate) * SimulationRate;
/// <summary>
- /// The tolerance of the mass grouping approximation in the simulation. A
- /// body is only accelerated when the ratio of the tree's width to the
- /// distance (from the tree's center of mass to the body) is less than this.
+ /// The tolerance of the mass grouping approximation in the simulation. A body is only accelerated when the
+ /// ratio of the tree's width to the distance (from the tree's center of mass to the body) is less than this.
/// </summary>
public const double TreeTheta = 0.5;
@@ -83,5 +91,37 @@ namespace StarSimLib
/// The amount by which the zoom level will be increased or decreased.
/// </summary>
public const double ZoomStep = 0.05;
+
+ /// <summary>
+ /// Converts an enumerable to its string form.
+ /// </summary>
+ /// <typeparam name="T">The type of item held in the enumerable.</typeparam>
+ /// <param name="enumerable">The enumerable instance to convert.</param>
+ /// <param name="itemPrinter">
+ /// The function used to convert a single item to a string, defaults to <see cref="object.ToString()"/></param>
+ /// <returns>The string representing the given enumerable.</returns>
+ public static string ConvertEnumerableToString<T>(IEnumerable<T> enumerable, Func<T, string> itemPrinter = null)
+ {
+ StringBuilder enumerableStringBuilder = new StringBuilder("[");
+
+ if (itemPrinter == null)
+ {
+ foreach (T item in enumerable)
+ {
+ enumerableStringBuilder.Append($"{item?.ToString() ?? "null"},");
+ }
+ }
+ else
+ {
+ foreach (T item in enumerable)
+ {
+ enumerableStringBuilder.Append($"{itemPrinter(item) ?? "null"},");
+ }
+ }
+
+ enumerableStringBuilder.Append("]");
+
+ return enumerableStringBuilder.ToString();
+ }
}
}
\ No newline at end of file
diff --git a/StarSim/StarSimLib/Data Structures/Body.cs b/StarSim/StarSimLib/Data Structures/Body.cs
@@ -116,11 +116,11 @@ namespace StarSimLib.Data_Structures
}
/// <summary>
- /// Gets the force vector for the attraction between <see cref="Body"/> A and <see cref="Body"/> B.
+ /// Computes the force vector for the gravitational attraction between <see cref="Body"/> A and <see cref="Body"/> B.
/// </summary>
/// <param name="a">The first <see cref="Body"/> instance.</param>
/// <param name="b">The second <see cref="Body"/> instance.</param>
- /// <returns></returns>
+ /// <returns>The computed force vector for the gravitational attraction.</returns>
public static Vector4 GetForceBetween(Body a, Body b)
{
// Inlines the Body.DistanceTo(Body) as the position deltas need to be cached for later,
@@ -131,10 +131,42 @@ namespace StarSimLib.Data_Structures
// The distance between two bodies can be found via taking the magnitude of their displacements,
// as shown here via pythagoras
- double distance = Math.Sqrt(dx * dx + dy * dy + dz * dz);
+ double distance2 = dx * dx + dy * dy + dz * dz;
+ double distance = Math.Sqrt(distance2);
double numerator = Constants.G * a.Mass * b.Mass;
- double denominator = distance * distance + Constants.SofteningFactor2;
+ double denominator = distance2 + Constants.SofteningFactor2;
+
+ // Using the equation Force = Gravitational Constant * Mass(a) * Mass(b) / distance(a, b)^2
+ // with a softening factor, we get the attraction force vector between the 2 bodies
+ double force = numerator / denominator;
+
+ return new Vector4(force * dx / distance, force * dy / distance, force * dz / distance);
+ }
+
+ /// <summary>
+ /// Computes the force vector for the gravitational attraction between the <see cref="Body"/> A and the mass at
+ /// the given position.
+ /// </summary>
+ /// <param name="a">The <see cref="Body"/> instance.</param>
+ /// <param name="positionB">The position at which the given mass can be thought of as acting.</param>
+ /// <param name="massB">The mass for which to compute the gravitational attraction.</param>
+ /// <returns>The computed force vector for the gravitational attraction.</returns>
+ public static Vector4 GetForceBetween(Body a, Vector4 positionB, double massB)
+ {
+ // Inlines the Body.DistanceTo(Body) as the position deltas need to be cached for later,
+ // as well as to gain a small performance increase
+ double dx = positionB.X - a.Position.X,
+ dy = positionB.Y - a.Position.Y,
+ dz = positionB.Z - a.Position.Z;
+
+ // The distance between two bodies can be found via taking the magnitude of their displacements,
+ // as shown here via pythagoras
+ double distance2 = dx * dx + dy * dy + dz * dz;
+ double distance = Math.Sqrt(distance2);
+
+ double numerator = Constants.G * a.Mass * massB;
+ double denominator = distance2 + Constants.SofteningFactor2;
// Using the equation Force = Gravitational Constant * Mass(a) * Mass(b) / distance(a, b)^2
// with a softening factor, we get the attraction force vector between the 2 bodies
@@ -154,6 +186,15 @@ namespace StarSimLib.Data_Structures
}
/// <summary>
+ /// Updates the current force vector for this instance, by adding the given vector to it.
+ /// </summary>
+ /// <param name="forceVector">The force vector to add to this instances internal force vector.</param>
+ public void AddForce(Vector4 forceVector)
+ {
+ force += forceVector;
+ }
+
+ /// <summary>
/// Collides this instance with the given <see cref="Body"/> instance.
/// </summary>
/// <param name="otherBody">The other instance with which to collide.</param>
diff --git a/StarSim/StarSimLib/Data Structures/Octant.cs b/StarSim/StarSimLib/Data Structures/Octant.cs
@@ -188,42 +188,42 @@ namespace StarSimLib.Data_Structures
{
case PositionSpecifier.TopNorthWest:
return GetOrSetChildOctant(ref childOctants, 0,
- midpoint + new Vector4(-quarterSideLength, +quarterSideLength, +quarterSideLength),
+ midpoint + new Vector4(-halfSideLength, +halfSideLength, +halfSideLength),
halfSideLength);
case PositionSpecifier.TopNorthEast:
return GetOrSetChildOctant(ref childOctants, 1,
- midpoint + new Vector4(+quarterSideLength, +quarterSideLength, +quarterSideLength),
+ midpoint + new Vector4(+halfSideLength, +halfSideLength, +halfSideLength),
halfSideLength);
case PositionSpecifier.TopSouthEast:
return GetOrSetChildOctant(ref childOctants, 2,
- midpoint + new Vector4(+quarterSideLength, +quarterSideLength, -quarterSideLength),
+ midpoint + new Vector4(+halfSideLength, +halfSideLength, -halfSideLength),
halfSideLength);
case PositionSpecifier.TopSouthWest:
return GetOrSetChildOctant(ref childOctants, 3,
- midpoint + new Vector4(-quarterSideLength, +quarterSideLength, -quarterSideLength),
+ midpoint + new Vector4(-halfSideLength, +halfSideLength, -halfSideLength),
halfSideLength);
case PositionSpecifier.BottomNorthWest:
return GetOrSetChildOctant(ref childOctants, 4,
- midpoint + new Vector4(-quarterSideLength, -quarterSideLength, +quarterSideLength),
+ midpoint + new Vector4(-halfSideLength, -halfSideLength, +halfSideLength),
halfSideLength);
case PositionSpecifier.BottomNorthEast:
return GetOrSetChildOctant(ref childOctants, 5,
- midpoint + new Vector4(+quarterSideLength, -quarterSideLength, +quarterSideLength),
+ midpoint + new Vector4(+halfSideLength, -halfSideLength, +halfSideLength),
halfSideLength);
case PositionSpecifier.BottomSouthEast:
return GetOrSetChildOctant(ref childOctants, 6,
- midpoint + new Vector4(+quarterSideLength, -quarterSideLength, -quarterSideLength),
+ midpoint + new Vector4(+halfSideLength, -halfSideLength, -halfSideLength),
halfSideLength);
case PositionSpecifier.BottomSouthWest:
return GetOrSetChildOctant(ref childOctants, 7,
- midpoint + new Vector4(-quarterSideLength, -quarterSideLength, -quarterSideLength),
+ midpoint + new Vector4(-halfSideLength, -halfSideLength, -halfSideLength),
halfSideLength);
default:
@@ -231,5 +231,19 @@ namespace StarSimLib.Data_Structures
"The given specifier is outside of the valid range.");
}
}
+
+ #region Overrides of Object
+
+ /// <inheritdoc />
+ public override string ToString()
+ {
+ return $"Octant - Width: {sideLength}, Midpoint: {midpoint} " +
+ $"TNW: {childOctants[0]?.ToString() ?? "null"}, TNE: {childOctants[1]?.ToString() ?? "null"}, " +
+ $"TSE: {childOctants[2]?.ToString() ?? "null"}, TSW: {childOctants[3]?.ToString() ?? "null"}, " +
+ $"BNW: {childOctants[4]?.ToString() ?? "null"}, BNE: {childOctants[5]?.ToString() ?? "null"}, " +
+ $"BSE: {childOctants[6]?.ToString() ?? "null"}, BSW: {childOctants[7]?.ToString() ?? "null"}";
+ }
+
+ #endregion Overrides of Object
}
}
\ No newline at end of file
diff --git a/StarSim/StarSimLib/Data Structures/OctantTree.cs b/StarSim/StarSimLib/Data Structures/OctantTree.cs
@@ -14,11 +14,26 @@ namespace StarSimLib.Data_Structures
private readonly Octant octant;
/// <summary>
+ /// The aggregate mass of all the bodies held in this instance.
+ /// </summary>
+ private double aggregateMass;
+
+ /// <summary>
/// The <see cref="Body"/> instance that is held in this instance, be it real or an aggregate.
/// </summary>
private Body body;
/// <summary>
+ /// The total number of bodies held in this instance.
+ /// </summary>
+ private int bodyCount;
+
+ /// <summary>
+ /// The point at which all the mass seems to be concentrated.
+ /// </summary>
+ private Vector4 centreOfAggregateMass;
+
+ /// <summary>
/// The child octant tree instances of this instance.
/// </summary>
private OctantTree[] childTrees;
@@ -30,6 +45,11 @@ namespace StarSimLib.Data_Structures
public OctantTree(Octant octant)
{
this.octant = octant;
+ body = null;
+
+ bodyCount = 0;
+ aggregateMass = 0;
+ centreOfAggregateMass = new Vector4();
childTrees = new OctantTree[8];
}
@@ -54,6 +74,27 @@ namespace StarSimLib.Data_Structures
get { return SubTree(specifier); }
}
+ private void AddToChildTree(Body newBody)
+ {
+ for (int subTreeIndex = 0; subTreeIndex < 8; subTreeIndex++)
+ {
+ Vector4 subtreeLocation = octant[subTreeIndex].Midpoint;
+
+ // determine if the body is contained within the bounds of the subtree under
+ // consideration
+ if (Math.Abs(subtreeLocation.X - newBody.Position.X) <= octant.Length / 2
+ && Math.Abs(subtreeLocation.Y - newBody.Position.Y) <= octant.Length / 2
+ && Math.Abs(subtreeLocation.Z - newBody.Position.Z) <= octant.Length / 2)
+ {
+ if (childTrees[subTreeIndex] == null)
+ childTrees[subTreeIndex] =
+ new OctantTree(octant[subTreeIndex]);
+ childTrees[subTreeIndex].AddBody(newBody);
+ return;
+ }
+ }
+ }
+
/// <summary>
/// Returns the specified child octant tree instance, or instantiates a new octant tree if the specified child
/// instance is <c>null</c>. The newly constructed instance will then be returned.
@@ -82,48 +123,40 @@ namespace StarSimLib.Data_Structures
/// <param name="newBody">The <see cref="Body"/> instance to add.</param>
public void AddBody(Body newBody)
{
- if (body == null)
+ centreOfAggregateMass = (aggregateMass * centreOfAggregateMass + newBody.Mass * newBody.Position) / (aggregateMass + newBody.Mass);
+ aggregateMass += newBody.Mass;
+ bodyCount++;
+
+ if (bodyCount == 1)
{
// this is an empty instance that has not yet had any bodies added to it.
body = newBody;
}
+ else
+ {
+ AddToChildTree(newBody);
+
+ if (bodyCount == 2)
+ {
+ AddToChildTree(body);
+ }
+ }
+ /*
else if (IsExternal())
{
// this instance is 'external' and contains another body. figure out where the new body should go and
// create a new octant tree instance to hold the new body
- for (int i = 0; i < childTrees.Length; i++)
- {
- OctantTree tree = SubTree(i);
-
- if (body.IsInOctant(tree.octant))
- {
- tree.AddBody(body);
- break;
- }
- }
-
- AddBody(newBody);
+ AddToChildTree(newBody);
+ AddToChildTree(body);
}
else if (!IsExternal())
{
// this instance already has a body to represent it, and it is not an 'external' tree instance, that is
// it has child trees of its own. figure out in which child tree the new body should be stored and update
// any further child nodes
-
- // make the held body an aggregate body
- body.Collide(newBody);
-
- for (int i = 0; i < childTrees.Length; i++)
- {
- OctantTree tree = SubTree(i);
-
- if (newBody.IsInOctant(tree.octant))
- {
- tree.AddBody(newBody);
- break;
- }
- }
+ AddToChildTree(newBody);
}
+ */
}
/// <summary>
@@ -191,10 +224,11 @@ namespace StarSimLib.Data_Structures
/// <param name="referenceBody">The body instance against which force updates are made.</param>
public void UpdateForces(Body referenceBody)
{
+ /*
if (IsExternal())
{
// since this tree instance is 'external' it has no children. we can treat it as a single body
- if (body != referenceBody)
+ if (body != null && body != referenceBody)
{
referenceBody?.AddForce(body);
}
@@ -203,7 +237,10 @@ namespace StarSimLib.Data_Structures
{
// otherwise if the octant length divided by the distance to the body (the width to distance ratio) is
// within a defined tolerance, we consider the tree to be effectively a single massive body
- referenceBody?.AddForce(body);
+ if (body != null)
+ {
+ referenceBody?.AddForce(body);
+ }
}
else
{
@@ -211,9 +248,57 @@ namespace StarSimLib.Data_Structures
{
OctantTree tree = SubTree(i);
- tree.UpdateForces(referenceBody);
+ if (body != null)
+ {
+ tree.UpdateForces(referenceBody);
+ break;
+ }
+ }
+
+ foreach (OctantTree subtree in childTrees)
+ {
+ subtree?.UpdateForces(referenceBody);
+ }
+ }
+ */
+
+ double dx = centreOfAggregateMass.X - referenceBody.Position.X;
+ double dy = centreOfAggregateMass.Y - referenceBody.Position.Y;
+ double dz = centreOfAggregateMass.Z - referenceBody.Position.Z;
+ double distance2 = dx * dx + dy * dy + dz * dz;
+
+ // Case 1. The tree contains only one body and it is not the one in the
+ // tree so we can perform the acceleration.
+ //
+ // Case 2. The width to distance ratio is within the defined tolerance so
+ // we consider the tree to be effectively a single massive body and
+ // perform the acceleration.
+ if (bodyCount == 1 && referenceBody != body || octant.Length * octant.Length < Constants.TreeTheta * Constants.TreeTheta * distance2)
+ {
+ referenceBody.AddForce(Body.GetForceBetween(referenceBody, centreOfAggregateMass, aggregateMass));
+ }
+ // Case 3. More granularity is needed so we accelerate at the subtrees.
+ else if (childTrees != null)
+ {
+ foreach (OctantTree subtree in childTrees)
+ {
+ subtree?.UpdateForces(referenceBody);
}
}
}
+
+ #region Overrides of Object
+
+ /// <inheritdoc />
+ public override string ToString()
+ {
+ return $"Tree - Octant: {octant?.ToString() ?? "null"}, Body: {body?.ToString() ?? "null"}, " +
+ $"TNW: {childTrees[0]?.ToString() ?? "null"}, TNE: {childTrees[1]?.ToString() ?? "null"}, " +
+ $"TSE: {childTrees[2]?.ToString() ?? "null"}, TSW: {childTrees[3]?.ToString() ?? "null"}, " +
+ $"BNW: {childTrees[4]?.ToString() ?? "null"}, BNE: {childTrees[5]?.ToString() ?? "null"}, " +
+ $"BSE: {childTrees[6]?.ToString() ?? "null"}, BSW: {childTrees[7]?.ToString() ?? "null"}";
+ }
+
+ #endregion Overrides of Object
}
}
\ No newline at end of file
diff --git a/StarSim/StarSimLib/Physics/BodyUpdater.cs b/StarSim/StarSimLib/Physics/BodyUpdater.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using StarSimLib.Data_Structures;
@@ -17,12 +18,6 @@ namespace StarSimLib.Physics
public static class BodyUpdater
{
/// <summary>
- /// Represents the main universe. Anything outside this octant of space is not updated when using the
- /// <see cref="UpdateBodiesBarnesHut"/> update method.
- /// </summary>
- public static readonly Octant UniverseOctant = new Octant(new Vector4(), Constants.UniverseSize);
-
- /// <summary>
/// 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="bodies">The collection of <see cref="Body"/>s whose positions to update.</param>
@@ -30,13 +25,19 @@ namespace StarSimLib.Physics
public static void UpdateBodiesBarnesHut(IEnumerable<Body> bodies, double deltaTime)
{
IEnumerable<Body> bodyEnumerable = bodies as Body[] ?? bodies.ToArray();
- OctantTree barnesHutTree = new OctantTree(UniverseOctant);
+
+ // root octant represents the main universe. Anything outside this octant of space is not updated
+ Octant universeOctant = new Octant(new Vector4(), Constants.UniverseSize * 1.1);
+
+ OctantTree barnesHutTree = new OctantTree(universeOctant);
// we construct our barnes-hut octant tree
foreach (Body body in bodyEnumerable)
{
- if (body.IsInOctant(UniverseOctant))
+ if (body.IsInOctant(universeOctant))
{
+ Console.WriteLine($"Body (during tree construction): {body}");
+
// only update a body's position if it is within the bounds of the universe
barnesHutTree.AddBody(body);
}
@@ -45,14 +46,23 @@ namespace StarSimLib.Physics
// we update the positions of the bodies in the populated tree
foreach (Body body in bodyEnumerable)
{
+ Console.WriteLine($"Body (before position update): {body}");
+
+ if (body == null)
+ {
+ continue;
+ }
+
body.ResetForce();
- if (body.IsInOctant(UniverseOctant))
+ if (body.IsInOctant(universeOctant))
{
barnesHutTree.UpdateForces(body);
body.Update(deltaTime);
}
+
+ Console.WriteLine($"Body (after position update): {body}");
}
}
diff --git a/StarSim/StarSimLib/StarSimLib.xml b/StarSim/StarSimLib/StarSimLib.xml
@@ -34,6 +34,12 @@
The gravitational constant (m^3 kg^-1 s^-2).
</summary>
</member>
+ <member name="F:StarSimLib.Constants.MinimumTreeWidth">
+ <summary>
+ The minimum width of a tree. Subtrees are not created when if their width would be smaller than this value,
+ to prevent widths of NaN as a result of division errors.
+ </summary>
+ </member>
<member name="F:StarSimLib.Constants.SecondsPerTick">
<summary>
The number of seconds that each simulation tick represents.
@@ -71,9 +77,8 @@
</member>
<member name="F:StarSimLib.Constants.TreeTheta">
<summary>
- The tolerance of the mass grouping approximation in the simulation. A
- body is only accelerated when the ratio of the tree's width to the
- distance (from the tree's center of mass to the body) is less than this.
+ The tolerance of the mass grouping approximation in the simulation. A body is only accelerated when the
+ ratio of the tree's width to the distance (from the tree's center of mass to the body) is less than this.
</summary>
</member>
<member name="F:StarSimLib.Constants.UniverseSize">
@@ -86,6 +91,16 @@
The amount by which the zoom level will be increased or decreased.
</summary>
</member>
+ <member name="M:StarSimLib.Constants.ConvertEnumerableToString``1(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.String})">
+ <summary>
+ Converts an enumerable to its string form.
+ </summary>
+ <typeparam name="T">The type of item held in the enumerable.</typeparam>
+ <param name="enumerable">The enumerable instance to convert.</param>
+ <param name="itemPrinter">
+ The function used to convert a single item to a string, defaults to <see cref="M:System.Object.ToString"/></param>
+ <returns>The string representing the given enumerable.</returns>
+ </member>
<member name="T:StarSimLib.Contexts.SimulatorContext">
<summary>
Represents the solar simulation database.
@@ -200,11 +215,21 @@
</member>
<member name="M:StarSimLib.Data_Structures.Body.GetForceBetween(StarSimLib.Data_Structures.Body,StarSimLib.Data_Structures.Body)">
<summary>
- Gets the force vector for the attraction between <see cref="T:StarSimLib.Data_Structures.Body"/> A and <see cref="T:StarSimLib.Data_Structures.Body"/> B.
+ Computes the force vector for the gravitational attraction between <see cref="T:StarSimLib.Data_Structures.Body"/> A and <see cref="T:StarSimLib.Data_Structures.Body"/> B.
</summary>
<param name="a">The first <see cref="T:StarSimLib.Data_Structures.Body"/> instance.</param>
<param name="b">The second <see cref="T:StarSimLib.Data_Structures.Body"/> instance.</param>
- <returns></returns>
+ <returns>The computed force vector for the gravitational attraction.</returns>
+ </member>
+ <member name="M:StarSimLib.Data_Structures.Body.GetForceBetween(StarSimLib.Data_Structures.Body,StarSimLib.Data_Structures.Vector4,System.Double)">
+ <summary>
+ Computes the force vector for the gravitational attraction between the <see cref="T:StarSimLib.Data_Structures.Body"/> A and the mass at
+ the given position.
+ </summary>
+ <param name="a">The <see cref="T:StarSimLib.Data_Structures.Body"/> instance.</param>
+ <param name="positionB">The position at which the given mass can be thought of as acting.</param>
+ <param name="massB">The mass for which to compute the gravitational attraction.</param>
+ <returns>The computed force vector for the gravitational attraction.</returns>
</member>
<member name="M:StarSimLib.Data_Structures.Body.AddForce(StarSimLib.Data_Structures.Body)">
<summary>
@@ -213,6 +238,12 @@
</summary>
<param name="otherBody">The other body to calculate the force between.</param>
</member>
+ <member name="M:StarSimLib.Data_Structures.Body.AddForce(StarSimLib.Data_Structures.Vector4)">
+ <summary>
+ Updates the current force vector for this instance, by adding the given vector to it.
+ </summary>
+ <param name="forceVector">The force vector to add to this instances internal force vector.</param>
+ </member>
<member name="M:StarSimLib.Data_Structures.Body.Collide(StarSimLib.Data_Structures.Body)">
<summary>
Collides this instance with the given <see cref="T:StarSimLib.Data_Structures.Body"/> instance.
@@ -532,6 +563,9 @@
Thrown when the given specifier does not equate to one of the values in the <see cref="T:StarSimLib.Data_Structures.PositionSpecifier"/> enum.
</exception>
</member>
+ <member name="M:StarSimLib.Data_Structures.Octant.ToString">
+ <inheritdoc />
+ </member>
<member name="T:StarSimLib.Data_Structures.OctantTree">
<summary>
A tree of <see cref="T:StarSimLib.Data_Structures.Octant"/> instances, where each node has 8 children.
@@ -542,11 +576,26 @@
The <see cref="T:StarSimLib.Data_Structures.Octant"/> of space managed by this instance.
</summary>
</member>
+ <member name="F:StarSimLib.Data_Structures.OctantTree.aggregateMass">
+ <summary>
+ The aggregate mass of all the bodies held in this instance.
+ </summary>
+ </member>
<member name="F:StarSimLib.Data_Structures.OctantTree.body">
<summary>
The <see cref="T:StarSimLib.Data_Structures.Body"/> instance that is held in this instance, be it real or an aggregate.
</summary>
</member>
+ <member name="F:StarSimLib.Data_Structures.OctantTree.bodyCount">
+ <summary>
+ The total number of bodies held in this instance.
+ </summary>
+ </member>
+ <member name="F:StarSimLib.Data_Structures.OctantTree.centreOfAggregateMass">
+ <summary>
+ The point at which all the mass seems to be concentrated.
+ </summary>
+ </member>
<member name="F:StarSimLib.Data_Structures.OctantTree.childTrees">
<summary>
The child octant tree instances of this instance.
@@ -625,6 +674,9 @@
</summary>
<param name="referenceBody">The body instance against which force updates are made.</param>
</member>
+ <member name="M:StarSimLib.Data_Structures.OctantTree.ToString">
+ <inheritdoc />
+ </member>
<member name="T:StarSimLib.Data_Structures.OrbitTracer">
<summary>
Represents a series of points denoting the previous positions of a <see cref="T:StarSimLib.Data_Structures.Body"/> instance. Used to render
@@ -1254,12 +1306,6 @@
Provides methods for updating <see cref="T:StarSimLib.Data_Structures.Body"/> instance positions.
</summary>
</member>
- <member name="F:StarSimLib.Physics.BodyUpdater.UniverseOctant">
- <summary>
- Represents the main universe. Anything outside this octant of space is not updated when using the
- <see cref="M:StarSimLib.Physics.BodyUpdater.UpdateBodiesBarnesHut(System.Collections.Generic.IEnumerable{StarSimLib.Data_Structures.Body},System.Double)"/> update method.
- </summary>
- </member>
<member name="M:StarSimLib.Physics.BodyUpdater.UpdateBodiesBarnesHut(System.Collections.Generic.IEnumerable{StarSimLib.Data_Structures.Body},System.Double)">
<summary>
Updates the positions of all the given <see cref="T:StarSimLib.Data_Structures.Body"/>s with O(n^2) time complexity, with the given time step.