Saturday 15 March 2014

Programming Gravity

One of these days I'd really like to make a universe simulator. The kind of thing where you could create a whole heap of planets and stars and watch them collide and orbit each other. A couple of weeks ago I thought I'd have a crack at programming some gravity. I did a little of my own research and then I contacted a friend of mine who studied physics and we put together some formulas.



The experiment went well. I made a simple GUI application with two buttons and applied the laws of the universe to these buttons. They began to gravitate towards each other. I felt very empowered, because even though all I'd done is made a couple of buttons gravitate towards towards each other, I'd also created a universe in my computer. I'm going to share a bare-bones example here which details only the maths behind it all.

There's several things to consider when doing this. First of all, you need a position structure. This should include either X and Y or X, Y and Z:


typedef struct {
  double x;
  double y;
  double z;
} position_t;

This structure represents a position in 2d or 3d space. Then you need a function to calculate the distance between two points. Depending on whether you want your universe to be 2d or 3d, you'll need the appropriate function. I made both anyway, even though my universe was 2d:

double distance2d(position_t *a, position_t *b)
{
  
  return sqrt( pow((b->x  - a->x), 2) + pow((b->y  - a->y), 2) );
  
}

double distance3d(position_t *a, position_t *b)
{
  
  double xd, yd, zd;
  xd = b->x - a->x;
  yd = b->y - a->y;
  zd = b->z - a->z;
  
  return sqrt( (xd*xd) + (yd*yd) + (zd*zd) );
  
}

Square roots are accurate but slow. If you wanted to calculate the distance faster but less accurately, there are other techniques around. Speed wasn't an issue for my experiment.

Next you need a class or structure to represent an object in space. This structure should contain the mass of the object, its position, its acceleration and its velocity. All of these variables are required to calculate the gravitational pull.

typedef struct {
  position_t position;
  double mass, velocity, acceleration;
} object_t;

With two of these objects created and distanced apart you can then make them gravitate toward each other in the next step. My example here is simple and only takes into account the X axis.

int main()
{
  
  position_t a = { 0, 0, 0 };
  position_t b = { 10, 10, 10 };
  
  // establish our two bodies
  object_t bodya = { a, 999999999, 0, 0 };
  object_t bodyb = { a, 444444444, 0, 0 };
  
  // press enter to go forwards, or q to quit
  while(getch() != 'q')
  {
    
    // calculate the distance between the objects
    double d = distance2d(&a, &b);
    
    // calculate the force
    double f = (6.67 * pow((1*10), -11)) * (bodya.mass * bodyb.mass)/pow(d, 2);
    
    // calculate the acceleration
    bodya.acceleration = f/bodya.mass;
    bodyb.acceleration = f/bodyb.mass;
    
    // calculate the velocity
    bodya.velocity += bodya.acceleration*1;
    bodyb.velocity += bodyb.acceleration*1;
    
    // calculate the position
    bodya.position.x += bodya.velocity;
    bodyb.position.x += bodyb.velocity;
    
    printf("Body A:\n\tPosition: x(%lf), y(%lf)\n\tVelocity: %f\nBody B:\n\tPosition: x(%lf), y(%lf)\n\tVelocity: %f\n",
      bodya.position.x, bodya.position.y, bodya.velocity,
      bodyb.position.x, bodyb.position.y, bodyb.velocity);
    
  }
  
  return 0;
  
}

I'm not a physicist, so maybe there are some errors in my calculations. But I'm quite certain that this is correct. It'd certainly seem so based off the numbers.

2 comments:

  1. Are there visuals for the program you wrote for this? I'd like to see.
    I noted that you accounted for the distance and gravitational force for the mass variable. But I'm a bit worried about the accuracy as you're dealing with exceedingly large values and small decimals.

    ReplyDelete
  2. If you have a program called Xojo (www.xojo.com) then I can give you the basic GUI test I did with the two buttons gravitating toward each other.

    ReplyDelete