public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = Vector.Vector_Copy(Comparison.Position);
            Force.Magnitude = Vector.Vector_Dot(Input.Position, Comparison.Position) * Comparison.Position.Magnitude / 2;

            //Return the new net force
            return Force;
        }
        public override void Seed(Simulation Input)
        {
            //Make sure we have somthing to work with
            if (Input.SimUniverse == null) return;
            if (Input.SimUniverse.Particles == null) return;
            if (Input.SimUniverse.Particles.Count == 0) return;

            foreach (Particle P in Input.SimUniverse.Particles)
            {
                SeedParticle(P, Input.SimUniverse.Boundary.Radius);
            }
        }
        public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = new Vector(Input.NetForce.Capacity);

            //Make sure both our input and comparison particles have "mass"
            if (!Input.HasProperty("Mass") || !Comparison.HasProperty("Mass")) return Force;

            //Now we calculate the actual distance between the particles (we will need this later)
            double ActualDistance = (Comparison.Position - Input.Position).Magnitude;
            if (ActualDistance == 0) return new Vector(Input.Acceleration.Count);

            //Assume a precision of zero
            if ((ActualDistance - Input.Radius - Comparison.Radius) <= 0)
            {
                //Return no change in acceleration
                return new Vector(Input.Acceleration.Count);
            }

            //If the "SofteningValue" simulation parameter is available to us:
            double Denominator = System.Math.Pow((ActualDistance * ActualDistance), (3.0 / 2.0));

            //Get all of our needed parts
            double InputMass = Input.GetPropertyVal("Mass");
            double ComparisonMass = Comparison.GetPropertyVal("Mass");

            //For each dimension of movement/location:
            for (int i = 0; i < Force.Capacity; i++)
            {
                //Calculate the component distance of this dimension
                double ComponentDistance = Comparison.Position[i] - Input.Position[i];

                //Calculate the new force
                Force[i] = (SimMath.GenerateRandomDouble(-ComparisonMass, ComparisonMass) * ComponentDistance) / Denominator;
            }

            //Return the new net force
            return Force;
        }
        public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = new Vector(Input.NetForce.Capacity);

            //Make sure both our input and comparison particles have "mass"
            if (!Input.HasProperty("Mass") || !Comparison.HasProperty("Mass")) return Force;

            //Now we calculate the actual distance between the particles (we will need this later)
            double ActualDistance = (Comparison.Position - Input.Position).Magnitude;
            if (ActualDistance == 0) return new Vector(Input.Acceleration.Count);

            //If the "Precision" simulation parameter is available to us:
            if (Sim.Parameters.HasParam("Precision"))
            {
                //Check to see if the actual distance is under the precision value
                if ((ActualDistance - Input.Radius - Comparison.Radius) <= Sim.Parameters.GetParam("Precision"))
                {
                    //Return no change in acceleration
                    return new Vector(Input.Acceleration.Count);
                }
            }
            else //Otherwise:
            {
                //Assume a precision of zero
                if ((ActualDistance - Input.Radius - Comparison.Radius) <= 0)
                {
                    //Return no change in acceleration
                    return new Vector(Input.Acceleration.Count);
                }
            }

            //If the "SofteningValue" simulation parameter is available to us:
            double Denominator;
            if (Sim.Parameters.HasParam("SofteningValue"))
            {
                //Calculate the denominator of the equation
                double SofteningValue = Sim.Parameters.GetParam("SofteningValue");
                Denominator = System.Math.Pow(((ActualDistance * ActualDistance) + (SofteningValue * SofteningValue)), (3.0 / 2.0));
            }
            else //Otherwise:
            {
                //Calculate the denominator of the equation
                Denominator = System.Math.Pow((ActualDistance * ActualDistance), (3.0 / 2.0));
            }

            //Get all of our needed parts
            double InputMass = Input.GetPropertyVal("Mass");
            double ComparisonMass = Comparison.GetPropertyVal("Mass");
            double GravitationalConstant;
            if (Sim.Parameters.HasParam("GravitationalConstant"))
            {
                GravitationalConstant = Sim.Parameters.GetParam("GravitationalConstant");
            }
            else
            {
                GravitationalConstant = PhysicsConstants.GravitationalConstant;
            }

            //For each dimension of movement/location:
            for (int i = 0; i < Force.Capacity; i++)
            {
                //Calculate the component distance of this dimension
                double ComponentDistance = Comparison.Position[i] - Input.Position[i];

                //Calculate the new force
                Force[i] = GravitationalConstant * (InputMass * ComparisonMass * ComponentDistance) / Denominator;
            }

            //Return the new net force
            return Force;
        }
        private void hardInitializeVeryLargeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try { this.CurrentSimulation.Stop(); }
            catch (Exception) { }
            this.Grid.VG_ClearPointWatchers();
            this.Grid.VG_ClearPoints();
            this.CurrentSimulation = new Simulation(this.Grid);
            this.CurrentSimulation.SimUniverse = new Universe(3);
            this.CurrentSimulation.SimUniverse.Boundary = new UniverseBoundary(150, this.LoadedAssets.AvailableScripts.ExtractScript<BoundaryScript>("Perfectly Inelastic"));
            this.CurrentSimulation.LinkedUpdateScript = this.LoadedAssets.AvailableScripts.ExtractScript<UpdateScript>("Basic");
            this.CurrentSimulation.Interactions = new InteractionScripts();
            this.CurrentSimulation.Interactions.Add(this.LoadedAssets.AvailableScripts.ExtractScript<ParticleInteractionScript>("Classical Gravity"));
            this.CurrentSimulation.Parameters = new SimulationParameters();
            this.CurrentSimulation.Parameters.Add(new SimulationParameter("MaximumVelocity", 10));
            this.CurrentSimulation.Parameters.Add(new SimulationParameter("MinimumAcceleration", 0.1));
            this.CurrentSimulation.Parameters.Add(new SimulationParameter("GravitationalConstant", PhysicsConstants.GravitationalConstant * 1E12));
            this.CurrentSimulation.Parameters.Add(new SimulationParameter("ElectrostaticConstant", PhysicsConstants.ElectrostaticConstant * 1E12));
            this.CurrentSimulation.Parameters.Add(new SimulationParameter("MagneticPermeability", PhysicsConstants.MagneticPermeability * 1E30));
            this.CurrentSimulation.SimUniverse.Particles = DEBUG_InitializeParticles(150, this.CurrentSimulation.SimUniverse.Boundary.Radius, SimMath.GenerateRandomDouble(1, 5), this.CurrentSimulation.SimUniverse.NumberDimensions);

            this.Grid.VG_3DMode = true;
            this.Grid.VG_3DCameraPosition[2] = -300;
            this.Grid.VG_Point3DCameraToOrigin();
            this.Grid.VG_PlotPointWatcherTrails = false;
            this.Grid.VG_HighDefinition = false;
            ((VG_Series)(this.Grid.Series[0])).VG_PointMode_OFF();
            this.Grid.VG_PointWatcherTrailFrequency = 1;
            this.Grid.VG_ClearPointWatchers();
            foreach (Particle P in this.CurrentSimulation.SimUniverse.Particles) this.Grid.VG_AddPointWatcher(P, 5, false);
            PopulateUniverseBoundaryMenu();
            PopulateUpdateScriptMenu();
            ApplyThemeColor();
            SetRadiusTextBoxText();
            this.CurrentSimulation.PlotParticles();
        }
        /// <summary>
        /// Loads a simulation object as the current simulation (automatically displaying any neccessary dialogs)
        /// NOT DONE
        /// </summary>
        /// <param name="SimulationToLoad">The simulation object to load</param>
        public void Load_Simulation(Simulation SimulationToLoad)
        {
            //If we are given a null simulation to load, return
            if (SimulationToLoad == null) return;

            //If we were already working on a simulation:
            if (this.CurrentSimulation != null)
            {
                //Ask the user if they want to save their simulation
                var Result = MetroFramework.MetroMessageBox.Show(this, "Would you like to save your current simulation?", "Save Current Simulation?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
                if (Result == System.Windows.Forms.DialogResult.Yes)
                {
                    //Save the old simulation
                }
                else if (Result == System.Windows.Forms.DialogResult.Cancel)
                {
                    //Do nothing
                    return;
                }
            }

            //Load the simulation by copying over the reference
            this.CurrentSimulation = SimulationToLoad;
        }
 /// <summary>
 /// Modifies the positions of particles and other properties of an input universe
 /// </summary>
 /// <param name="Input">The universe to modify</param>
 public abstract void Seed(Simulation Input);