Beispiel #1
0
 public void Set()
 {
     if (parent.ActiveText != this.name.Text && parent.Active != -1)
     {
         var elements = new Structures.OrbitalElements()
         {
             semilatusrectum        = SLRScale.Value * AU,
             eccentricity           = EScale.Value,
             inclination            = IncScale.Value * deg,
             ascendingNodeLongitude = ANLScale.Value * deg,
             periapsisArgument      = PAScale.Value * deg,
             trueAnomaly            = TAScale.Value * deg
         };
         body = new Structures.Body(menu.new_bodies.FirstOrDefault(b => b.body.name == parent.ActiveText).body, elements);
     }
     body.name    = this.name.Text;
     body.stdGrav = Math.Pow(Math.E, MassScale.Value) * G * 1e22;
     body.radius  = RadiusScale.Value * 1e3;
     body.color   = new Vector3(RScale.Value, GScale.Value, BScale.Value);
 }
        }                        // paramaterless constructor for serialisation

        public Body(Body parent, OrbitalElements elements)
        {
            // First check the values are reasonable. If parent == null it is assumed that
            // position and velocity are set explicitly, and this constructor is not used
            if (parent == null)
            {
                return;
            }
            this.parent = parent;
            if (elements.eccentricity < 0 ||
                elements.semilatusrectum < 0 ||
                elements.inclination < 0 ||
                elements.inclination > Math.PI ||
                elements.ascendingNodeLongitude < 0 ||
                elements.ascendingNodeLongitude >= 2 * Math.PI ||
                elements.periapsisArgument < 0 ||
                elements.periapsisArgument >= 2 * Math.PI ||
                elements.trueAnomaly < 0 ||
                elements.trueAnomaly >= 2 * Math.PI
                )
            {
                // Throw an exception if the arguments are out of bounds
                throw new ArgumentException();
            }
            // working in perifocal coordinates (periapsis along the x axis, orbit in the x,y plane):
            double  mag_peri_radius = elements.semilatusrectum / (1 + elements.eccentricity * Math.Cos(elements.trueAnomaly));
            Vector3 peri_radius     = mag_peri_radius * new Vector3(Math.Cos(elements.trueAnomaly), Math.Sin(elements.trueAnomaly), 0);
            Vector3 peri_velocity   = Math.Sqrt(parent.stdGrav / elements.semilatusrectum)
                                      * new Vector3(
                -Math.Sin(elements.trueAnomaly),
                Math.Cos(elements.trueAnomaly) + elements.eccentricity,
                0
                );
            // useful constants to setup transformation matrix
            var sini = Math.Sin(elements.inclination);             // i <- inclination
            var cosi = Math.Cos(elements.inclination);
            var sino = Math.Sin(elements.ascendingNodeLongitude);  // capital omega <- longitude of ascending node
            var coso = Math.Cos(elements.ascendingNodeLongitude);
            var sinw = Math.Sin(elements.periapsisArgument);       // omega <- argument of periapsis
            var cosw = Math.Cos(elements.periapsisArgument);
            // Transform perifocal coordinates to i,j,k coordinates
            Matrix3 transform = new Matrix3(
                new Vector3(
                    coso * cosw - sino * sinw * cosi,
                    -coso * sinw - sino * cosw * cosi,
                    sino * sini
                    ),
                new Vector3(
                    sino * cosw + coso * sinw * cosi,
                    -sino * sinw + coso * cosw * cosi,
                    -coso * sini
                    ),
                new Vector3(
                    sinw * sini,
                    cosw * sini,
                    cosi
                    )
                );

            // add the parent's position and velocity since that could be orbiting something too
            this.position = transform * peri_radius + parent.position;
            this.velocity = transform * peri_velocity + parent.velocity;
        }
        public static bool BodyTest()
        {
            var sun = new Body {
                stdGrav = 1.3271440019e20,
                radius  = 6.95e8
            };
            var elem = new OrbitalElements()
            {
                semilatusrectum        = 3.2 * AU,
                eccentricity           = 0.7,
                inclination            = 1.2,
                ascendingNodeLongitude = 0.1,
                periapsisArgument      = 4.3,
                trueAnomaly            = 3.7
            };
            Body sun2 = (Body)sun.Clone();

            sun2.position += new Vector3(3, 2, 6);
            sun2.velocity += new Vector3(1, 5, 3);
            var e1 = new Body(sun, elem);
            var e2 = new Body(sun2, elem);

            e2.position -= new Vector3(3, 2, 6);
            e2.velocity -= new Vector3(1, 5, 3);
            if (e1.position != e2.position || e1.velocity != e2.velocity)
            {
                Console.WriteLine("Parent r/v not considered");
                return(false);
            }
            for (double i = 0; i < Math.PI; i += 0.2)
            {
                for (double j = 0; j < 2 * Math.PI; j += 0.2)
                {
                    for (double k = 0; k < 2 * Math.PI; k += 0.2)
                    {
                        for (double l = 0; l < 2 * Math.PI; l += 0.2)
                        {
                            for (double m = 0; l < 1; l += 0.1)
                            {
                                var earthElements = new OrbitalElements()
                                {
                                    semilatusrectum        = 1 * AU,
                                    eccentricity           = m,
                                    inclination            = i,
                                    ascendingNodeLongitude = j,
                                    periapsisArgument      = k,
                                    trueAnomaly            = l
                                };
                                var earth = new Body(sun, earthElements)
                                {
                                    stdGrav = 3.986004419e14,
                                    radius  = 6.371e6,
                                    color   = new Vector3(0, 0.2, 0.8),
                                };
                                if (m == 0)
                                {
                                    if (!(Math.Abs(Vector3.Magnitude(earth.velocity) - 3e4) < 1e3))
                                    {
                                        Console.WriteLine($"{i},{j},{k},{l},{earth.velocity}");
                                        return(false);
                                    }
                                    else if (!(Math.Abs(Vector3.Magnitude(earth.position) - 1 * AU) < 1e-4))
                                    {
                                        Console.WriteLine($"{i},{j},{k},{l},{Vector3.Magnitude(earth.position)/AU}");
                                        return(false);
                                    }
                                }
                                var earthElements2 = new OrbitalElements(earth.position, earth.velocity, sun.stdGrav);
                                foreach (Tuple <string, double, double> t in new List <Tuple <string, double, double> >()
                                {
                                    new Tuple <string, double, double>("l", earthElements.ascendingNodeLongitude, earthElements2.ascendingNodeLongitude),
                                    new Tuple <string, double, double>("e", earthElements.eccentricity, earthElements2.eccentricity),
                                    new Tuple <string, double, double>("i", earthElements.inclination, earthElements2.inclination),
                                    new Tuple <string, double, double>("w", earthElements.periapsisArgument, earthElements2.periapsisArgument),
                                    new Tuple <string, double, double>("p", earthElements.semilatusrectum, earthElements2.semilatusrectum),
                                    new Tuple <string, double, double>("v", earthElements.trueAnomaly, earthElements2.trueAnomaly),
                                })
                                {
                                    if ((t.Item2 - t.Item3) / t.Item2 > 1e-6)
                                    {
                                        if (t.Item1 == "l" && i == 0 ||
                                            (t.Item1 == "w" || t.Item1 == "v") && m == 0)
                                        {
                                            // They are undefined, don't worry
                                            continue;
                                        }
                                        Console.WriteLine($"Orbital element test failed: {t.Item1}, {t.Item2}, {t.Item3}, {((t.Item2 - t.Item3)/t.Item2)*100}%");
                                        return(false);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            var elemx = new OrbitalElements()
            {
                inclination            = 2 * Math.PI,
                ascendingNodeLongitude = 7.5 * Math.PI,
                trueAnomaly            = 27 * Math.PI,
                periapsisArgument      = 3.75 * Math.PI
            };

            if (
                elemx.inclination > 1e-10 ||
                (elemx.ascendingNodeLongitude - (1.5 * Math.PI)) / (1.5 * Math.PI) > 1e-10 ||
                (elemx.trueAnomaly - Math.PI) / Math.PI > 1e-10 ||
                (elemx.periapsisArgument - 1.75 * Math.PI) / (1.75 * Math.PI) > 1e-10
                )
            {
                Console.WriteLine("Implicit angle readjustment failed");
                Console.WriteLine(elemx.trueAnomaly / Math.PI);
            }
            return(true);
        }