Click here to Skip to main content
11,429,154 members (63,094 online)
Click here to Skip to main content

Fun With Gravity

, 28 Jul 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
A gravity simulation particle system.

Introduction

This article is a fine example of what happens when programmers get bored. There's nothing exciting in the code, maybe a gentle introduction to GDI+. It was just a fun project to mess with, and it's addictive to play with. So I thought I might share it.

I was thinking about the fact that every particle in the universe is constantly gravitationally affected by every particle in the universe, and wanted to see what it would look like modeled in software. It's been a number of years since I cracked a Physics book, so I can't guaranty my accuracy with this project... But it sure is pretty.

The Code

Calculating Acceleration Due to Gravity

The method I chose for calculating the gravitational effect of each particle pn on particle p is this: I create a vector that extends from one particle to the other by subtracting ps location vector from pns location.

Vector unit = p2.Location - p.Location;

Then, calculate the magnitude of the resulting vector:

float magnitude = (float)Math.Sqrt(
      (unit.X * unit.X)
    + (unit.Y * unit.Y)
    + (unit.Z * unit.Z)
);

Then, you have what you need to calculate the acceleration.

float factor = (
    GravitationalConstant * (
        (p.Mass * p2.Mass) / (magnitude * magnitude * magnitude)
    )
) / p.Mass;

The resulting vector is what's needed to alter your particle's velocity due to the gravity of particle pn. I originally started with the actual gravitational constant G = 6.672e-11, but scaled it larger for simulation's sake, allowing smaller masses to be used.

The full calculation loop looks like this. Notice that for each particle, you calculate the gravitational effect on it by every other particle.

foreach (Particle p in particles) {
    ...
    if (particles.Count > 1) { 
        Vector a = new Vector();
        foreach (Particle p2 in particles) {
            if (object.ReferenceEquals(p, p2)) { continue; }
            Vector unit = p2.Location - p.Location;
            float magnitude = (float)Math.Sqrt(
                (unit.X * unit.X)
                + (unit.Y * unit.Y)
                + (unit.Z * unit.Z));
            float factor = (GravitationalConstant * (
                (p.Mass * p2.Mass) / (magnitude * magnitude * magnitude)
            )) / p.Mass;
            unit *= factor;
            a += unit;
        }
        p.Velocity += a;
    }
    ...
}

Conservation of Momentum with Inelastic Collisions

My collision detection is primitive. I'm only looking to see if a particle's bounding rectangle intersects with another. The Z axes was an afterthought, and in case the X and Y are intersecting, I look to see if the Z locations are with 5 of each other. I got lazy, what can I say. I wasn't that interested in the Z axes, but wanted to include it in the calculations.

In any event, when two particles collide, I combine their colors and masses. I increase their size slightly. And combine their momentum to find the resulting particle's velocity.

private Particle Merge(Particle i, Particle j, Graphics g) {
    ...
    Vector v = ((i.Velocity * i.Mass) + (j.Velocity * j.Mass));
    v /= i.Mass + j.Mass;
    ...
}

The Demo Application

Controls

There are menu options to Start, Stop, and Pause the simulation. Pause has a keyboard shortcut of F5, and Start has Ctrl+E (Execute from SQL Query Analyzer Smile | :) . You must start the simulation before you can add particles, and you can restart at any time to reset everything. Clicking anywhere in the picture box will create a particle at that location. The text boxes to the left under the check boxes determines the properties that the new particle will have. You can set the X, Y, and Z components of its initial velocity, its mass, and its size in pixels.

Buttons

The three buttons under the text boxes, labeled "B", "M" & "S", set the properties to predefined values for convenience. "B" creates a massive particle, "M" creates a medium, and "S" creates a small. The "Background" button allows you to change the picture box's background color.

Check Boxes

  • Trace: Toggles tracing. Tracing now shows a trail for each particle.
  • Collisions: Toggles collision detection.
  • Show Vel: Shows the velocity vector in red.
  • Vel Box: Shows the velocity vector's bounding box.
  • Show Acc: Shows the acceleration vector in the particle's color.
  • Acc Box: Shows the acceleration vector's bounding box.

The visual representation of the velocity and acceleration vectors is scaled up quite a bit so that they are visible at the scales I was working with. With more massive examples, the acceleration vector line can be pretty long. I may look at changing it to scale variably based on masses, but probably not.

Velocity Vector Velocity Box Acceleration Vector Acceleration Box Velocity & Acceleration

Particle ListView

Finally, the list view at the bottom of the window shows some attributes of the particles. The list view now shows all particles but only when paused. While paused, if you select particles in the list view and hit DELETE, it will remove the selected particles.

Conclusion

I don't think there's much to learn from this project, other than some simple GDI+ usage, and I suppose if you're not familiar with operator overloads, you could find some interesting things in the Vector class. It was just a fun project to play with, and it looks pretty cool. If I get bored enough some day, I may see about turning it into a screensaver.

History

07/24/2008

Based on the suggestions by protix & Zimriel I've updated calculations to more accurately represent orbits. I fixed the non-tracing flickering by drawing to an image and replacing the picturebox's image (poor man's double buffer). And tracing has been redone as well. Originally, I wanted to clear the image with a white color with a low alpha so that previous draws would fade. However, drawing an alpha color to the entire image takes far too long. In the end, I wound up having each particle keep track of a number of previous position, which get redrawn with decreasing alpha values. There may be a better solution, but this works for now.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

BoneSoft
Software Developer (Senior) BoneSoft Software
United States United States
I've been in software development for more than a decade now. Originally with ASP 2.0 and VB6. I worked in Japan for a year doing Java. And have been with C# ever since.

In 2005 I founded BoneSoft Software where I sell a small number of developer tools.
Group type: Organisation (No members)



Comments and Discussions

 
GeneralMy vote of 5 Pin
Philip P Liebscher26-May-11 19:58
memberPhilip P Liebscher26-May-11 19:58 
GeneralMy vote of 5 Pin
alain_dionne29-Mar-11 6:30
memberalain_dionne29-Mar-11 6:30 
GeneralThumbs up! Pin
Bigdeak10-Jun-10 6:15
memberBigdeak10-Jun-10 6:15 
General[Message Removed] Pin
immetoz6-Oct-08 8:49
memberimmetoz6-Oct-08 8:49 
JokeGood Article, But ... Pin
Member 477036529-Jul-08 0:36
memberMember 477036529-Jul-08 0:36 
GeneralRe: Good Article, But ... Pin
canozurdo29-Jul-08 3:23
membercanozurdo29-Jul-08 3:23 
GeneralRe: Good Article, But ... Pin
Xmen 22-Jan-09 17:25
member Xmen 22-Jan-09 17:25 
GeneralFun Pin
Timmy Kokke28-Jul-08 21:14
memberTimmy Kokke28-Jul-08 21:14 
Generalgood Pin
david bagaturia20-Jul-08 21:06
memberdavid bagaturia20-Jul-08 21:06 
GeneralNice project Pin
fgjsdhgsdhg343242342323422-Aug-07 10:04
memberfgjsdhgsdhg343242342323422-Aug-07 10:04 
GeneralRe: Nice project Pin
BoneSoft22-Aug-07 13:10
memberBoneSoft22-Aug-07 13:10 
GeneralOrbits Pin
protix26-Jul-07 2:32
memberprotix26-Jul-07 2:32 
Hi,

as I am phisicist by education (however 8 years ago that I've done serious physics stuff, software instead Wink | ;) ) the orbits problem caught my curiosity...

After some code poking I believe to know the reason for the non elliptical orbits.

The first (and most responsible) is the implemented gravitational law:
For it to be *our* gravitation law it should read:

float factor = (GravitationalConstant
* ((p.Mass * p2.Mass) / (magnitude * magnitude * magnitude))) / p.Mass;

instead of

float factor = (GravitationalConstant
* ((p.Mass * p2.Mass) / (magnitude * magnitude))) / p.Mass;

because you multiply with the distance vector (called "unit" in the code).

So you use just another force in the code which happens to be proportional to
1 / distance instead of 1 / distance ^ 2 as the real world gravitation force.

The second (and less haevy in effect) inaccuracy is the point where
p.Update() is called to update the particles location. If it is done this way, the location on a particle is updated *before* it is used again on the next loop to calculate the distance. Correctly the locations of all particles should be updated *after* all calculation on a time tick is done. An possibility to do this is to split the

foreach (Particle p in particles)
{
"do everything"
}

loop in three loops:

foreach (Particle p in particles)
{
"do velocity calculation";
}

foreach (Particle p in particles)
{
p.Update();
}

foreach (Particle p in particles)
{
"do the drawing";
}

After theese changes a test with 2 "Big" masses, one with y-velocity = -0.1 somewhere on the left and one with y-velocity = 0.1 on the right will result in neat eliptical orbits.


Some improvement would be the explicit usage of physical time steps between two calculations. As it is the use of

p.Velocity += a; // a is actually the acceleration

as well as (in Update())

this.location += this.velocity;

containes an implicit time step = 1 (arbitrary units, or seconds if all other units are SI units).

An explicit time step would read:
velocity += acceleration * timeStep;
and
location += velocity * timeStep;

Then one can variate the exactness of the simulation by making the time step smaller (more exact) or bigger (less exact). In reality the "time step" is infinitelly small (in Newtonian physics).

One can estimate the exactness of the simulation by monitoring the overall energy and overall momentum - both should stay unchanged (energy and momentum conservation). In the simulation they do only for sufficently small time steps. It is funny to observe how energy and momentum is "generated" when two particles get to close to each other (collisions turned off).

And finally, when doing simulations with many particles, numerics is an issue, using double instead of float is probably neccessary then.

Hope this helps to improve the simulation a bit Smile | :) ,

Plamen Petrow.

GeneralRe: Orbits Pin
BoneSoft26-Jul-07 5:09
memberBoneSoft26-Jul-07 5:09 
AnswerRe: Orbits Pin
protix26-Jul-07 22:45
memberprotix26-Jul-07 22:45 
GeneralRe: Orbits Pin
protix26-Jul-07 22:48
memberprotix26-Jul-07 22:48 
GeneralRe: Orbits Pin
Zimriel14-Nov-07 20:21
memberZimriel14-Nov-07 20:21 
GeneralGreat Work!! Pin
Neo_Shehpar24-Jul-07 12:35
memberNeo_Shehpar24-Jul-07 12:35 
GeneralRe: Great Work!! Pin
BoneSoft24-Jul-07 17:34
memberBoneSoft24-Jul-07 17:34 
GeneralPhysics from a physicist Pin
Kory.Postma24-Jul-07 2:20
memberKory.Postma24-Jul-07 2:20 
GeneralRe: Physics from a physicist Pin
BoneSoft24-Jul-07 3:18
memberBoneSoft24-Jul-07 3:18 
GeneralRe: Physics from a physicist Pin
BoneSoft24-Jul-07 7:02
memberBoneSoft24-Jul-07 7:02 
GeneralSuggestion Pin
Josh Smith23-Jul-07 9:12
mvpJosh Smith23-Jul-07 9:12 
GeneralRe: Suggestion Pin
BoneSoft23-Jul-07 17:50
memberBoneSoft23-Jul-07 17:50 
GeneralCool! Pin
Jay Gatsby22-Jul-07 22:42
memberJay Gatsby22-Jul-07 22:42 
GeneralGravity Screen Saver Pin
Obiwan Jacobi22-Jul-07 20:59
memberObiwan Jacobi22-Jul-07 20:59 
GeneralRe: Gravity Screen Saver Pin
BoneSoft23-Jul-07 4:53
memberBoneSoft23-Jul-07 4:53 
GeneralRe: Gravity Screen Saver Pin
Chris Losinger3-Dec-07 11:31
memberChris Losinger3-Dec-07 11:31 
GeneralDang! Now I just have to know... Pin
charlieg22-Jul-07 14:04
membercharlieg22-Jul-07 14:04 
GeneralRe: Dang! Now I just have to know... Pin
BoneSoft22-Jul-07 18:25
memberBoneSoft22-Jul-07 18:25 
GeneralVery nice Pin
Bradml22-Jul-07 3:49
memberBradml22-Jul-07 3:49 
QuestionExtra Mass? Pin
Berg4950822-Jul-07 2:19
memberBerg4950822-Jul-07 2:19 
AnswerRe: Extra Mass? Pin
Obble25-Jul-07 11:16
memberObble25-Jul-07 11:16 
GeneralCool article Pin
Joergen Sigvardsson22-Jul-07 1:07
memberJoergen Sigvardsson22-Jul-07 1:07 
GeneralAwesome! Pin
Stephan Poirier21-Jul-07 21:11
memberStephan Poirier21-Jul-07 21:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150428.2 | Last Updated 28 Jul 2008
Article Copyright 2007 by BoneSoft
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid