Beispiel #1
0
 /// <summary>
 /// Determines the new P and V for each body in the universe
 /// </summary>
 /// <param name="universe">The Universe to update</param>
 /// <param name="dt">the timestep of the update</param>
 internal void CalcBodyTrajectory(Universe universe, double dt)
 {
     if (parallel)
     {
         Parallel.ForEach(universe.GetBodies(), body =>
         {
             UpdateEuler(universe, body, dt);
         });
     }
     else
     {
         if (universe.useRelative)
         {
             foreach (Body body in universe.GetBodies())
             {
                 UpdateEulerV(universe, body, dt);
             }
             CorrectForMovingReferenceFrames(universe, dt);
             foreach (Body body in universe.GetBodies())
             {
                 UpdateEulerP(body, dt);
             }
         }
         else
         {
             foreach (Body body in universe.GetBodies())
             {
                 UpdateEuler(universe, body, dt);
             }
         }
     }
 }
        public void BaseScaleForUniverse(Form form, Universe universe, double correction = 1.0)
        {
            if (form == null)
            {
                return;
            }
            double maxD = 0;

            if (universe.useRelative)
            {
                foreach (RelativeBody body in universe.GetBodies())
                {
                    double bodyD = body.GetAbsP().Mag();
                    maxD = bodyD > maxD ? bodyD : maxD;
                }
            }
            else
            {
                foreach (RelativeBody body in universe.GetBodies())
                {
                    double bodyD = body.p.Mag();
                    maxD = bodyD > maxD ? bodyD : maxD;
                }
            }
            double smallerSide = Math.Min(form.ClientRectangle.Width / 2.0, form.ClientRectangle.Height / 2.0);

            scale = smallerSide / maxD / correction;
        }
        public void focusNext(Universe universe)
        {
            if (focus == null)
            {
                focus = universe.GetBodies().First();
            }
            int ind = universe.GetBodies().IndexOf(focus);

            ind++;
            focus = ind >= universe.GetBodies().Count ? null : universe.GetBodies()[ind];
            Debug.WriteLine($"New Focus: {(focus == null ? "Barycenter" : focus.ToString())}");
        }
Beispiel #4
0
        internal void CheckCollision(Universe universe)
        {
            //TODO: rework, verify, and find a way to intelligently use spatial partitioning
            List <Body> allBodies = universe.GetBodies();

            for (int i = 0; i < allBodies.Count(); i++)
            {
                Body a = allBodies[i];
                if (a.deletionFlag)
                {
                    continue;
                }
                for (int j = i + 1; j < allBodies.Count(); j++)
                {
                    Body b = allBodies[j];
                    if (b.deletionFlag)
                    {
                        continue;
                    }
                    Vector pRel = a.pNext - b.pNext;
                    double r    = a.r + b.r;
                    if (pRel.Mag() < r)
                    {
                        b.deletionFlag = true;
                        a.vNext        = (a.m * a.vNext + b.m * b.vNext) / (a.m + b.m);
                        a.rho          = (a.m + b.m) / ((a.m / a.rho) + (b.m / b.rho));
                        a.m           += b.m;
                        a.EstR();
                    }
                }
            }
        }
Beispiel #5
0
 /// <summary>
 /// For each body in universe, set the current P and V values to be the calculated 'next' values
 /// </summary>
 /// <param name="universe">Universe to update</param>
 internal void UpdateBodies(Universe universe)
 {
     foreach (Body body in universe.GetBodies())
     {
         body.UpdateBodyPV();
     }
 }
Beispiel #6
0
        /// <summary>
        /// When using reference frame modes, the fact that reference frames can accelerate needs to be corrected for
        /// </summary>
        /// <param name="universe">universe to correct</param>
        /// <param name="dt">timestep used</param>
        internal void CorrectForMovingReferenceFrames(Universe universe, double dt)
        {
            // need to adjust the position/velocity vectors to account for the fact that reference frames are moving and accelerating.
            RelativeBody center = (RelativeBody)universe.GetBodies().First();  //TODO: rewrite to handle binary-style cases

            center.correctForMovingReferenceFrames(dt);
        }
Beispiel #7
0
        /// <summary>
        /// Adjusts the position of all bodies in universe such that the barycenter is kept as close to the origin as possible
        /// </summary>
        /// <param name="universe"></param>
        internal void FixBarycenter(Universe universe)
        {
            //TODO: consider setting 'barycenter velocity' to zero here as well
            foreach (Body body in universe.GetBodies())
            {
                if (body.pinned)
                {
                    return; //if there are any pinned bodies, then we shouldn't need to do this (?)
                }
            }
            if (universe.useRelative)
            {
                Vector weightedP  = new Vector();
                Body   center     = universe.GetBodies().First(); //TODO: Fix for cases where multiple bodies have "null" as parent e.g binary stars
                Vector barycenter = (center as RelativeBody).GetFamilyBarycenter();

                //Debug.WriteLine($"bary: {barycenter.ToString()}");
                center.p = -barycenter;
            }
            else
            {
                Vector weightedP = new Vector();
                double mass      = 0;
                foreach (Body body in universe.GetBodies())
                {
                    weightedP += body.m * body.p;
                    mass      += body.m;
                }
                weightedP /= mass;
                //Debug.WriteLine($"bary: {weightedP.ToString()}");
                foreach (Body body in universe.GetBodies())
                {
                    body.p -= weightedP;
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Calculate the acceleration vector of a given body due to the other bodies in a given universe
        /// </summary>
        /// <param name="universe">the universe containing the bodies imparting gravitational force</param>
        /// <param name="body">the body to calculate acceleration for</param>
        /// <returns>the calculated acceleration vector</returns>
        internal Vector Acceleration(Universe universe, Body body)
        {
            Vector a = new Vector(0, 0, 0);

            foreach (Body other in universe.GetBodies())
            {
                if (other == body)
                {
                    continue;
                }
                Vector dist = Distance(body, other, universe.useRelative);
                a += universe.G * other.m * dist.Normal() / (Math.Pow(dist.Mag(), 2));
            }
            return(a);
        }
        internal void RenderUniverseFromFocus(Graphics dc, Pen pen, Universe universe, RelativeBody focus)
        {
            RelativeBody center   = (RelativeBody)universe.GetBodies().First(); // TODO: better handle binary-type cases
            Pen          childPen = new Pen(Color.Blue, 1);

            if (focus == null && center != null)
            {
                RecursiveRenderChildren(dc, childPen, center, center.p);
            }
            else
            {
                RecursiveRenderChildren(dc, childPen, focus, Vector.zeroVect);
                RecursiveRenderParents(dc, pen, focus, Vector.zeroVect);
            }
        }
        internal void renderBodies(Graphics dc, Universe universe)
        {
            if (universe == null)
            {
                return;
            }
            Pen BodyPen = new Pen(Color.Black, 1);

            if (universe.useRelative)
            {
                RenderUniverseFromFocus(dc, BodyPen, universe, focus as RelativeBody);
            }
            else
            {
                foreach (Body body in universe.GetBodies())
                {
                    renderBody(dc, BodyPen, body);
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Determine if any Bodies have moved far enough away from their parent, or close enough to a 'better' parent to justify updating their reference frame
        /// </summary>
        /// <param name="universe">The universe to consider for required reference frame updates</param>
        internal void UpdateReferenceFramesIfNecessary(Universe universe)
        {
            if (!universe.useRelative)
            {
                return; //non-relative mode doesn't use reference frames
            }

            foreach (RelativeBody body in universe.GetBodies())
            {
                // If body leaves Hill sphere of parent, set reference frame to grandparent.
                // TODO: Look into precomputing hill sphere radius
                if (body.parent != null && body.parent.parent != null)
                {
                    double hillRad = body.parent.p.Mag() * Math.Pow(body.parent.m / 3.0 / body.parent.parent.m, 1.0 / 3.0);
                    if (body.p.Mag() > hillRad)
                    {
                        body.p += body.parent.p;
                        body.v += body.parent.v;
                        (body.parent.parent as RelativeBody).AdoptChild(body);
                    }
                }
                // TODO: check to see if body has entered hill sphere of any more-massive siblings.
            }
        }
        public static Universe GenPseudoRandomUniverse(
            bool relative  = true,
            int seed       = 0,
            int count      = 20,
            int nestFactor = 2,
            double mScale  = 100.0,
            double mRatio  = 1000.0,
            double dScale  = 500.0)
        {
            Random   random         = seed == 0 ? new Random() : new Random(seed);
            Universe uni            = new Universe(relative);
            double   avgSplitFactor = Math.Log(count, nestFactor);
            int      total          = 1;

            if (relative)
            {
                RelativeBody center = new RelativeBody(mScale, "0_*");
                uni.AddBody(center);
                int continues = 0;
                while (total < count)
                {
                    RelativeBody host = (RelativeBody)uni.GetBodies()[random.Next(0, uni.GetBodies().Count())];
                    if (host.parentDepth() > nestFactor - 1)
                    {
                        continues++;
                        if (continues < 4)
                        {
                            continue;
                        }
                        host = center;
                    }
                    continues = 0;
                    double mass = (host.m / mRatio) * Math.Pow(2, -host.children.Count());
                    //double mag = random.NextDouble() * dScale * host.m / mScale;
                    double mag;
                    if (host == center)
                    {
                        mag = dScale;
                    }
                    else
                    {
                        mag = host.p.Mag() * Math.Pow(host.m / (3 * host.parent.m), 0.333) / 4.0;
                    }
                    mag *= random.NextDouble();
                    double theta    = random.NextDouble() * Math.PI * 2;
                    Vector distance = new Vector(mag * Math.Cos(theta), mag * Math.Sin(theta), 0);

                    string name;
                    if (host == center)
                    {
                        name = $"{center.children.Count() + 1}_*";
                    }
                    else if (host.parentDepth() == 1)
                    {
                        name = $"{host.name.Substring(0, host.name.Length - 1)}{host.children.Count() + 1}";
                    }
                    else
                    {
                        name = $"{host.name}_{host.children.Count() + 1}";
                    }

                    RelativeBody addition = new RelativeBody(distance, host, mass, lbl: $"{name}");
                    uni.AddBody(addition);
                    total++;
                }
            }
            uni.HeirarchicalSort();
            return(uni);
        }