示例#1
0
        /// <summary>
        /// Gets the descending node of orbit.
        /// </summary>
        /// <param name="desc">The desc.</param>
        /// <returns><c>true</c> if descending node exists, otherwise <c>false</c></returns>
        public bool GetDescendingNode(out Vector3d desc)
        {
            var norm     = CelestialBodyUtils.CrossProduct(OrbitNormal, EclipticNormal);
            var s        = CelestialBodyUtils.DotProduct(CelestialBodyUtils.CrossProduct(norm, SemiMajorAxisBasis), OrbitNormal) < 0;
            var ecc      = 0d;
            var trueAnom = Vector3d.Angle(norm, -CenterPoint) * Mathd.Deg2Rad;

            if (Eccentricity < 1)
            {
                var cosT = Math.Cos(trueAnom);
                ecc = Math.Acos((Eccentricity + cosT) / (1d + Eccentricity * cosT));
                if (s)
                {
                    ecc = Mathd.PI_2 - ecc;
                }
            }
            else
            {
                trueAnom = Vector3d.Angle(norm, CenterPoint) * Mathd.Deg2Rad;
                if (trueAnom >= Mathd.Acos(-1d / Eccentricity))
                {
                    desc = new Vector3d();
                    return(false);
                }
                var cosT = Math.Cos(trueAnom);
                ecc = CelestialBodyUtils.Acosh((Eccentricity + cosT) / (1 + Eccentricity * cosT)) * (s ? -1 : 1);
            }
            desc = GetFocalPositionAtEccentricAnomaly(ecc);
            return(true);
        }
示例#2
0
        public bool GetAscendingNode(out Vector3d asc)
        {
            var norm     = CelestialBodyUtils.CrossProduct(orbitNormal, eclipticNormal);
            var s        = CelestialBodyUtils.DotProduct(CelestialBodyUtils.CrossProduct(norm, semiMajorAxisBasis), orbitNormal) < 0;
            var ecc      = 0d;
            var trueAnom = Vector3d.Angle(norm, centerPoint) * Mathd.Deg2Rad;

            if (eccentricity < 1)
            {
                var cosT = System.Math.Cos(trueAnom);
                ecc = System.Math.Acos((eccentricity + cosT) / (1d + eccentricity * cosT));
                if (!s)
                {
                    ecc = Mathd.PI_2 - ecc;
                }
            }
            else
            {
                trueAnom = Vector3d.Angle(-norm, centerPoint) * Mathd.Deg2Rad;
                if (trueAnom >= Mathd.Acos(-1d / eccentricity))
                {
                    asc = new Vector3d();
                    return(false);
                }
                var cosT = System.Math.Cos(trueAnom);
                ecc = CelestialBodyUtils.Acosh((eccentricity + cosT) / (1 + eccentricity * cosT)) * (!s ? -1 : 1);
            }
            asc = GetFocalPositionAtEccentricAnomaly(ecc);
            return(true);
        }
        /// <summary>
        /// Draw two crossing lines in scene view.
        /// </summary>
        private static void DrawX(Vector3 pos, float size, Color col, Vector3 normal, Vector3 up)
        {
            Handles.color = col;
            Vector3 right = CelestialBodyUtils.CrossProduct(up, normal).normalized;

            Handles.DrawLine(pos + up * size, pos - up * size);
            Handles.DrawLine(pos + right * size, pos - right * size);
        }
示例#4
0
        public static Vector3[] CalcOrbitPoints(Vector3 attractorPos, Vector3 bodyPos, double attractorMass, double bodyMass, Vector3 relVelocity, double gConst, int pointsCount)
        {
            if (pointsCount < 3 || pointsCount > 10000)
            {
                return(new Vector3[0]);
            }
            var focusPoint            = CalcCenterOfMass(attractorPos, attractorMass, bodyPos, bodyMass);
            var radiusVector          = bodyPos - focusPoint;
            var radiusVectorMagnitude = radiusVector.magnitude;
            var orbitNormal           = CelestialBodyUtils.CrossProduct(radiusVector, relVelocity);
            var MG              = (attractorMass + bodyMass) * gConst;
            var eccVector       = CelestialBodyUtils.CrossProduct(relVelocity, orbitNormal) / (float)MG - radiusVector / radiusVectorMagnitude;
            var focalParameter  = orbitNormal.sqrMagnitude / MG;
            var eccentricity    = eccVector.magnitude;
            var minorAxisNormal = -CelestialBodyUtils.CrossProduct(orbitNormal, eccVector).normalized;
            var majorAxisNormal = -CelestialBodyUtils.CrossProduct(orbitNormal, minorAxisNormal).normalized;

            orbitNormal.Normalize();
            double  orbitCompressionRatio;
            double  semiMajorAxys;
            double  semiMinorAxys;
            Vector3 relFocusPoint;
            Vector3 centerPoint;

            if (eccentricity < 1)
            {
                orbitCompressionRatio = 1 - eccentricity * eccentricity;
                semiMajorAxys         = focalParameter / orbitCompressionRatio;
                semiMinorAxys         = semiMajorAxys * System.Math.Sqrt(orbitCompressionRatio);
                relFocusPoint         = (float)semiMajorAxys * eccVector;
                centerPoint           = focusPoint - relFocusPoint;
            }
            else
            {
                orbitCompressionRatio = eccentricity * eccentricity - 1f;
                semiMajorAxys         = focalParameter / orbitCompressionRatio;
                semiMinorAxys         = semiMajorAxys * System.Math.Sqrt(orbitCompressionRatio);
                relFocusPoint         = -(float)semiMajorAxys * eccVector;
                centerPoint           = focusPoint - relFocusPoint;
            }

            var    points = new Vector3[pointsCount];
            double eccVar = 0f;

            for (int i = 0; i < pointsCount; i++)
            {
                Vector3 result = eccentricity < 1 ?
                                 new Vector3((float)(System.Math.Sin(eccVar) * semiMinorAxys), -(float)(System.Math.Cos(eccVar) * semiMajorAxys)) :
                                 new Vector3((float)(System.Math.Sinh(eccVar) * semiMinorAxys), (float)(System.Math.Cosh(eccVar) * semiMajorAxys));
                eccVar   += Mathf.PI * 2f / (float)(pointsCount - 1);
                points[i] = minorAxisNormal * result.x + majorAxisNormal * result.y + centerPoint;
            }
            return(points);
        }
        private void DrawInclinationMarkForBody(CelestialBody body, float scale)
        {
            var norm = CelestialBodyUtils.CrossProduct((Vector3)body.OrbitData.OrbitNormal, (Vector3)_simControl.EclipticNormal);

            Handles.color = Color.white;
            var p = CelestialBodyUtils.CrossProduct(norm, (Vector3)_simControl.EclipticNormal).normalized;

            Handles.DrawLine((Vector3)body.OrbitFocusPoint, (Vector3)body.OrbitFocusPoint + p * 3f * scale);
            Handles.DrawLine((Vector3)body.OrbitFocusPoint, (Vector3)body.OrbitFocusPoint + CelestialBodyUtils.RotateVectorByAngle(p, (float)body.OrbitData.Inclination, -norm.normalized) * 3f * scale);
            Handles.DrawWireArc((Vector3)body.OrbitFocusPoint, -norm, p, (float)(body.OrbitData.Inclination * Mathd.Rad2Deg), 1f * scale);
            DrawLabelScaled((Vector3)body.OrbitFocusPoint + p * scale, (body.OrbitData.Inclination * Mathd.Rad2Deg).ToString("0") + "\u00B0", Color.white, 10);
        }
        /// <summary>
        /// Draw simple arrow in scene window at given world coordinates
        /// </summary>
        private static void DrawArrow(Vector3 from, Vector3 to, Color col, Vector3 normal)
        {
            var   dir        = to - from;
            float dist       = dir.magnitude;
            var   dirNorm    = dir / dist; //normalized vector
            float headSize   = dist / 6f;
            var   _colBefore = Handles.color;

            Handles.color = col;
            Vector3 sideNormal = CelestialBodyUtils.CrossProduct(dir, normal).normalized;

            Handles.DrawLine(from, from + dirNorm * (dist - headSize));
            Handles.DrawLine(from + dirNorm * (dist - headSize) + sideNormal * headSize / 2f, from + dirNorm * (dist - headSize) - sideNormal * headSize / 2f);
            Handles.DrawLine(from + dirNorm * (dist - headSize) + sideNormal * headSize / 2f, from + dir);
            Handles.DrawLine(from + dirNorm * (dist - headSize) - sideNormal * headSize / 2f, from + dir);
            Handles.color = _colBefore;
        }
示例#7
0
        /// <summary>
        /// Calculates the full state of orbit from current body position, attractor position, attractor mass, velocity, and gravConstant.
        /// </summary>
        public void CalculateNewOrbitData()
        {
            IsDirty = false;
            var MG = AttractorMass * GravitationalConstant;

            AttractorDistance = Position.magnitude;
            var angularMomentumVector = CelestialBodyUtils.CrossProduct(Position, Velocity);

            OrbitNormal = angularMomentumVector.normalized;
            Vector3d eccVector;

            // Check if zero lenght.
            if (OrbitNormal.sqrMagnitude < 0.9 || OrbitNormal.sqrMagnitude > 1.1)
            {
                OrbitNormal = CelestialBodyUtils.CrossProduct(Position, EclipticUp).normalized;
                eccVector   = new Vector3d();
            }
            else
            {
                eccVector = CelestialBodyUtils.CrossProduct(Velocity, angularMomentumVector) / MG - Position / AttractorDistance;
            }
            OrbitNormalDotEclipticNormal = CelestialBodyUtils.DotProduct(OrbitNormal, EclipticNormal);
            FocalParameter     = angularMomentumVector.sqrMagnitude / MG;
            Eccentricity       = eccVector.magnitude;
            EnergyTotal        = Velocity.sqrMagnitude - 2 * MG / AttractorDistance;
            SemiMinorAxisBasis = CelestialBodyUtils.CrossProduct(angularMomentumVector, eccVector).normalized;
            if (SemiMinorAxisBasis.sqrMagnitude < 0.5)
            {
                SemiMinorAxisBasis = CelestialBodyUtils.CrossProduct(OrbitNormal, Position).normalized;
            }
            SemiMajorAxisBasis = CelestialBodyUtils.CrossProduct(OrbitNormal, SemiMinorAxisBasis).normalized;
            Inclination        = Vector3d.Angle(OrbitNormal, EclipticNormal) * Mathd.Deg2Rad;
            if (Eccentricity < 1)
            {
                OrbitCompressionRatio = 1 - Eccentricity * Eccentricity;
                SemiMajorAxis         = FocalParameter / OrbitCompressionRatio;
                SemiMinorAxis         = SemiMajorAxis * Math.Sqrt(OrbitCompressionRatio);
                CenterPoint           = -SemiMajorAxis * eccVector;
                Period            = Mathd.PI_2 * Mathd.Sqrt(Mathd.Pow(SemiMajorAxis, 3) / MG);
                Apoapsis          = CenterPoint + SemiMajorAxisBasis * SemiMajorAxis;
                Periapsis         = CenterPoint - SemiMajorAxisBasis * SemiMajorAxis;
                PeriapsisDistance = Periapsis.magnitude;
                ApoapsisDistance  = Apoapsis.magnitude;
                TrueAnomaly       = Vector3d.Angle(Position, -SemiMajorAxisBasis) * Mathd.Deg2Rad;
                if (CelestialBodyUtils.DotProduct(CelestialBodyUtils.CrossProduct(Position, SemiMajorAxisBasis), OrbitNormal) < 0)
                {
                    TrueAnomaly = Mathd.PI_2 - TrueAnomaly;
                }
                EccentricAnomaly = CelestialBodyUtils.ConvertTrueToEccentricAnomaly(TrueAnomaly, Eccentricity);
                MeanAnomaly      = EccentricAnomaly - Eccentricity * Math.Sin(EccentricAnomaly);
            }
            else
            {
                OrbitCompressionRatio = Eccentricity * Eccentricity - 1;
                SemiMajorAxis         = FocalParameter / OrbitCompressionRatio;
                SemiMinorAxis         = SemiMajorAxis * Math.Sqrt(OrbitCompressionRatio);
                CenterPoint           = SemiMajorAxis * eccVector;
                Period            = double.PositiveInfinity;
                Apoapsis          = new Vector3d(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity);
                Periapsis         = CenterPoint + SemiMajorAxisBasis * (SemiMajorAxis);
                PeriapsisDistance = Periapsis.magnitude;
                ApoapsisDistance  = double.PositiveInfinity;
                TrueAnomaly       = Vector3d.Angle(Position, eccVector) * Mathd.Deg2Rad;
                if (CelestialBodyUtils.DotProduct(CelestialBodyUtils.CrossProduct(Position, SemiMajorAxisBasis), OrbitNormal) < 0)
                {
                    TrueAnomaly = -TrueAnomaly;
                }
                EccentricAnomaly = CelestialBodyUtils.ConvertTrueToEccentricAnomaly(TrueAnomaly, Eccentricity);
                MeanAnomaly      = Math.Sinh(EccentricAnomaly) * Eccentricity - EccentricAnomaly;
            }
        }
示例#8
0
        public void CalculateNewOrbitData()
        {
            isDirty = false;
            var MG = attractorMass * gravConst;

            attractorDistance = position.magnitude;
            var angularMomentumVector = CelestialBodyUtils.CrossProduct(position, velocity);

            orbitNormal = angularMomentumVector.normalized;
            Vector3d eccVector;

            if (orbitNormal.sqrMagnitude < 0.9 || orbitNormal.sqrMagnitude > 1.1)              //check if zero lenght
            {
                orbitNormal = CelestialBodyUtils.CrossProduct(position, eclipticUp).normalized;
                eccVector   = new Vector3d();
            }
            else
            {
                eccVector = CelestialBodyUtils.CrossProduct(velocity, angularMomentumVector) / MG - position / attractorDistance;
            }
            orbitNormalDotEclipticNormal = CelestialBodyUtils.DotProduct(orbitNormal, eclipticNormal);
            focalParameter = angularMomentumVector.sqrMagnitude / MG;
            eccentricity   = eccVector.magnitude;
            //if (debug) {
            //	string format = "0.0000000000";
            //	Debug.Log(
            //		"ECC: " + eccVector.ToString(format) + " LEN: " + eccVector.magnitude.ToString(format) + "\n" +
            //		"POS: " + position.ToString(format) + " LEN: " + position.magnitude.ToString(format) + "\n" +
            //		"POSNORM: " + ( position / attractorDistance ).ToString(format) + " LEN: " + ( position / attractorDistance ).magnitude.ToString(format) + "\n" +
            //		"VEL: " + velocity.ToString(format) + " LEN: " + velocity.magnitude.ToString(format) + "\n" +
            //		"POScrossVEL: " + angularMomentumVector.ToString(format) + " LEN: " + angularMomentumVector.magnitude.ToString(format) + "\n"
            //		);
            //}
            energyTotal        = velocity.sqrMagnitude - 2 * MG / attractorDistance;
            semiMinorAxisBasis = CelestialBodyUtils.CrossProduct(angularMomentumVector, eccVector).normalized;
            if (semiMinorAxisBasis.sqrMagnitude < 0.5)
            {
                semiMinorAxisBasis = CelestialBodyUtils.CrossProduct(orbitNormal, position).normalized;
            }
            semiMajorAxisBasis = CelestialBodyUtils.CrossProduct(orbitNormal, semiMinorAxisBasis).normalized;
            inclination        = Vector3d.Angle(orbitNormal, eclipticNormal) * Mathd.Deg2Rad;
            if (eccentricity < 1)
            {
                orbitCompressionRatio = 1 - eccentricity * eccentricity;
                semiMajorAxis         = focalParameter / orbitCompressionRatio;
                semiMinorAxis         = semiMajorAxis * System.Math.Sqrt(orbitCompressionRatio);
                centerPoint           = -semiMajorAxis * eccVector;
                period            = Mathd.PI_2 * Mathd.Sqrt(Mathd.Pow(semiMajorAxis, 3) / MG);
                apoapsis          = centerPoint + semiMajorAxisBasis * semiMajorAxis;
                periapsis         = centerPoint - semiMajorAxisBasis * semiMajorAxis;
                periapsisDistance = periapsis.magnitude;
                apoapsisDistance  = apoapsis.magnitude;
                trueAnomaly       = Vector3d.Angle(position, -semiMajorAxisBasis) * Mathd.Deg2Rad;
                if (CelestialBodyUtils.DotProduct(CelestialBodyUtils.CrossProduct(position, semiMajorAxisBasis), orbitNormal) < 0)
                {
                    trueAnomaly = Mathd.PI_2 - trueAnomaly;
                }
                eccentricAnomaly = CelestialBodyUtils.ConvertTrueToEccentricAnomaly(trueAnomaly, eccentricity);
                meanAnomaly      = eccentricAnomaly - eccentricity * System.Math.Sin(eccentricAnomaly);
            }
            else
            {
                orbitCompressionRatio = eccentricity * eccentricity - 1;
                semiMajorAxis         = focalParameter / orbitCompressionRatio;
                semiMinorAxis         = semiMajorAxis * System.Math.Sqrt(orbitCompressionRatio);
                centerPoint           = semiMajorAxis * eccVector;
                period            = double.PositiveInfinity;
                apoapsis          = new Vector3d(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity);
                periapsis         = centerPoint + semiMajorAxisBasis * (semiMajorAxis);
                periapsisDistance = periapsis.magnitude;
                apoapsisDistance  = double.PositiveInfinity;
                trueAnomaly       = Vector3d.Angle(position, eccVector) * Mathd.Deg2Rad;
                if (CelestialBodyUtils.DotProduct(CelestialBodyUtils.CrossProduct(position, semiMajorAxisBasis), orbitNormal) < 0)
                {
                    trueAnomaly = -trueAnomaly;
                }
                eccentricAnomaly = CelestialBodyUtils.ConvertTrueToEccentricAnomaly(trueAnomaly, eccentricity);
                meanAnomaly      = System.Math.Sinh(eccentricAnomaly) * eccentricity - eccentricAnomaly;
            }
        }