示例#1
0
        /// <summary>
        /// Return ratio of perturbation force from third body relative to attraction force of mainAttractor
        /// </summary>
        /// <param name="targetBody"></param>
        /// <param name="mainAttractor"></param>
        /// <param name="perturbatingAttractor"></param>
        public static double RelativePerturbationRatio(CelestialBody targetBody, CelestialBody mainAttractor, CelestialBody perturbatingAttractor)
        {
            double mainAcceleration = CelestialBodyUtils.AccelerationByAttractionForce(
                targetBody.position,
                mainAttractor.position,
                mainAttractor.MG).magnitude;
            double perturbAcceleration = CelestialBodyUtils.AccelerationByAttractionForce(
                targetBody.position,
                perturbatingAttractor.position,
                perturbatingAttractor.MG).magnitude;

            return(perturbAcceleration / mainAcceleration);
        }
        /// <summary>
        /// Calculate and apply n-body gravitational acceleration to target body, using algorythm Runge-Kutta.
        /// In result body will change it's velocity according to global gravity.
        /// </summary>
        /// <param name="body">Target body.</param>
        /// <param name="dt">Delta time.</param>
        /// <param name="minRange">Minimal attraction range for attractors.</param>
        /// <param name="maxRange">Maximal attraction range for attractors.</param>
        /// <param name="allAttractors">List of all attractors on scene.</param>
        public static void CalcAccelerationRungeKuttaForBody(CelestialBody body, double dt, double minRange, double maxRange, List <CelestialBody> allAttractors)
        {
            Vector3d result = Vector3d.zero;

            body._position += body.Velocity * (dt / 2d);
            for (int i = 0; i < allAttractors.Count; i++)
            {
                if (allAttractors[i] == body)
                {
                    continue;
                }
                var t1 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position,
                    allAttractors[i].Position,
                    allAttractors[i].MG,
                    minRange,
                    Mathd.Min(maxRange, allAttractors[i].MaxAttractionRange)
                    ) * dt;
                var t2 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position + t1 * 0.5d,
                    allAttractors[i].Position,
                    allAttractors[i].MG,
                    minRange,
                    Mathd.Min(maxRange, allAttractors[i].MaxAttractionRange)
                    ) * dt;
                var t3 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position + t2 * 0.5d,
                    allAttractors[i].Position,
                    allAttractors[i].MG,
                    minRange,
                    Mathd.Min(maxRange, allAttractors[i].MaxAttractionRange)
                    ) * dt;
                var t4 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position + t3,
                    allAttractors[i].Position,
                    allAttractors[i].MG,
                    minRange,
                    Mathd.Min(maxRange, allAttractors[i].MaxAttractionRange)
                    ) * dt;
                result += new Vector3d(
                    (t1.x + t2.x * 2d + t3.x * 2d + t4.x) / 6d,
                    (t1.y + t2.y * 2d + t3.y * 2d + t4.y) / 6d,
                    (t1.z + t2.z * 2d + t3.z * 2d + t4.z) / 6d);
            }
            if (!result.isZero)
            {
                body.Velocity += result;
            }
        }
        public void CalcAccelerationRungeKuttaForBody(CelestialBody body, double dt)
        {
            Vector3d result = Vector3d.zero;

            body._position += body.velocity * (dt / 2d);
            for (int i = 0; i < attractorsCache.Count; i++)
            {
                if (attractorsCache[i] == body)
                {
                    continue;
                }
                var t1 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position,
                    attractorsCache[i].position,
                    attractorsCache[i].MG,
                    minAttractionRange,
                    Mathd.Min(maxAttractionRange, attractorsCache[i].maxAttractionRange)
                    ) * dt;
                var t2 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position + t1 * 0.5d,
                    attractorsCache[i].position,
                    attractorsCache[i].MG,
                    minAttractionRange,
                    Mathd.Min(maxAttractionRange, attractorsCache[i].maxAttractionRange)
                    ) * dt;
                var t3 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position + t2 * 0.5d,
                    attractorsCache[i].position,
                    attractorsCache[i].MG,
                    minAttractionRange,
                    Mathd.Min(maxAttractionRange, attractorsCache[i].maxAttractionRange)
                    ) * dt;
                var t4 = CelestialBodyUtils.AccelerationByAttractionForce(
                    body._position + t3,
                    attractorsCache[i].position,
                    attractorsCache[i].MG,
                    minAttractionRange,
                    Mathd.Min(maxAttractionRange, attractorsCache[i].maxAttractionRange)
                    ) * dt;
                result += new Vector3d(
                    (t1.x + t2.x * 2d + t3.x * 2d + t4.x) / 6d,
                    (t1.y + t2.y * 2d + t3.y * 2d + t4.y) / 6d,
                    (t1.z + t2.z * 2d + t3.z * 2d + t4.z) / 6d);
            }
            body.velocity += result;
        }
        /// <summary>
        /// Calculate n-body gravitational acceleration at specified world point, using Euler algorythm.
        /// </summary>
        /// <param name="pos">World position.</param>
        /// <param name="minRange">Minimal attraction range for attractors.</param>
        /// <param name="maxRange">Maximal attraction range for attractors.</param>
        /// <param name="allAttractors">List of all attractors on scene.</param>
        /// <returns>Sum of accelerations vectors at position.</returns>
        public static Vector3d CalcAccelerationEulerInPoint(Vector3d pos, double minRange, double maxRange, List <CelestialBody> allAttractors)
        {
            Vector3d result = new Vector3d();

            for (int i = 0; i < allAttractors.Count; i++)
            {
                if (allAttractors[i].Position == pos)
                {
                    continue;
                }
                result += CelestialBodyUtils.AccelerationByAttractionForce(
                    pos,
                    allAttractors[i].Position,
                    allAttractors[i].MG,
                    minRange,
                    Mathd.Min(maxRange, allAttractors[i].MaxAttractionRange)
                    );
            }
            return(result);
        }
        public Vector3d CalcAccelerationEulerInPoint(Vector3d pos)
        {
            Vector3d result = new Vector3d();

            for (int i = 0; i < attractorsCache.Count; i++)
            {
                if (attractorsCache[i].position == pos)
                {
                    continue;
                }
                result += CelestialBodyUtils.AccelerationByAttractionForce(
                    pos,
                    attractorsCache[i].position,
                    attractorsCache[i].MG,
                    minAttractionRange,
                    Mathd.Min(maxAttractionRange, attractorsCache[i].maxAttractionRange)
                    );
            }
            return(result);
        }
        public void CalcAccelerationEulerForBody(CelestialBody body, double dt)
        {
            Vector3d result = Vector3d.zero;

            for (int i = 0; i < attractorsCache.Count; i++)
            {
                if (attractorsCache[i] == body)
                {
                    continue;
                }
                result += CelestialBodyUtils.AccelerationByAttractionForce(
                    body.position,
                    attractorsCache[i].position,
                    attractorsCache[i].MG,
                    minAttractionRange,
                    Mathd.Min(maxAttractionRange, attractorsCache[i].maxAttractionRange)
                    );
            }
            body.velocity += result * dt;
        }
        /// <summary>
        /// Calculate and apply n-body gravitational acceleration to target body, using Euler algorythm.
        /// In result body will change it's velocity according to global gravity.
        /// </summary>
        /// <param name="body">Target body.</param>
        /// <param name="dt">Delta time.</param>
        /// <param name="minRange">Minimal attraction range for attractors.</param>
        /// <param name="maxRange">Maximal attraction range for attractors.</param>
        /// <param name="allAttractors">List of all attractors on scene.</param>
        public static void CalcAccelerationEulerForBody(CelestialBody body, double dt, double minRange, double maxRange, List <CelestialBody> allAttractors)
        {
            Vector3d result = Vector3d.zero;

            for (int i = 0; i < allAttractors.Count; i++)
            {
                if (object.ReferenceEquals(allAttractors[i], body))
                {
                    continue;
                }
                result += CelestialBodyUtils.AccelerationByAttractionForce(
                    body.Position,
                    allAttractors[i].Position,
                    allAttractors[i].MG,
                    minRange,
                    Mathd.Min(maxRange, allAttractors[i].MaxAttractionRange)
                    );
            }
            if (!result.isZero)
            {
                body.Velocity += result * dt;
            }
        }