//////////////////////////////////////////////////////////////////// // Copyright © 2009 Carl Johansen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more // details (). //////////////////////////////////////////////////////////////////// using System.Collections.Generic; using System.Windows.Media.Media3D; namespace GravityDemo { public class OrbitStateVectorPair { public Vector3D Position { get; set; } public Vector3D Velocity { get; set; } } class NewtonianSystem { public IList Bodies { get; private set; } public float GravitationalConstant { get; private set; } // public RectangleF BoundingRectangle { get; set; } public delegate void CollisionHandler(NewtonianSystem system, Body body1, Body body2); public event CollisionHandler Collision; public NewtonianSystem() { Bodies = new List(); } public void AddBody(Body body) { Bodies.Add(body); } public Body AddBody(float mass, float radius, Vector3D position, Vector3D initialVelocity) { Body newBody = new Body(mass, radius, position, initialVelocity, GravitationalConstant); Bodies.Add(newBody); return newBody; } public void Heartbeat(float elapsedSeconds) { for (int i = 1; i < Bodies.Count; i++) { for (int j = 0; j < i; j++) { if (Bodies[i].Enabled && Bodies[j].Enabled) { ApplyGravitationalForce(Bodies[i], Bodies[j]); } } } for (int i = 0; i < Bodies.Count; i++) { if (Bodies[i].Enabled) { Bodies[i].Heartbeat(elapsedSeconds); } } } protected void ApplyGravitationalForce(Body b1, Body b2) { const float gravityEffectiveThreshold = 1e-7F; Vector3D separation = b1.Position - b2.Position; double distSquared = separation.LengthSquared; bool collision = distSquared <= (double)(b1.Radius + b2.Radius) * (b1.Radius + b2.Radius); float accelerationScalar1 = (float)(b2.GM / distSquared); float accelerationScalar2 = (float)(b1.GM / distSquared); if (accelerationScalar1 > gravityEffectiveThreshold || accelerationScalar2 > gravityEffectiveThreshold) { separation.Normalize(); if (accelerationScalar1 > gravityEffectiveThreshold) { b1.AddInstantaneousAcceleration(-Vector3D.Multiply(accelerationScalar1, separation)); } if (accelerationScalar2 > gravityEffectiveThreshold) { b2.AddInstantaneousAcceleration(Vector3D.Multiply(accelerationScalar2, separation)); } } if (collision && (Collision!=null)) { Collision(this, b1, b2); } } //public RectangleF GetBoundingRectangle() //{ // float minX=float.MaxValue, maxX=float.MinValue, minY=float.MaxValue, maxY=float.MinValue; // foreach (Body body in Bodies) // { // if (body.Position.X < minX) // minX = body.Position.X; // else if(body.p // } //} } }