You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

218 lines
5.0 KiB

  1. //Takes 2 galaxies as input.
  2. //Sets them up so that they will collide with each other.
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <math.h>
  8. //types that we need
  9. //TODO: put these in their own file
  10. typedef struct RigidMass
  11. {
  12. long mass;
  13. double vx, vy;
  14. double x, y;
  15. double dvx, dvy;
  16. double tick_time;
  17. } RigidMass_t;
  18. typedef struct config
  19. {
  20. int nStars;
  21. int imgW, imgH;
  22. int savePeriod;
  23. int iteration;
  24. char saveFile[255];
  25. } config_t;
  26. typedef struct point
  27. {
  28. double x;
  29. double y;
  30. } point_t;
  31. void loadGalaxy(char *filename, config_t *conf, RigidMass_t **stars)
  32. {
  33. FILE *fp;
  34. fp = fopen(filename, "r");
  35. //read config first
  36. fread(conf, sizeof(config_t), 1, fp);
  37. //read stars next
  38. *stars = malloc(sizeof(RigidMass_t) * conf->nStars);
  39. fread(*stars, sizeof(RigidMass_t), conf->nStars, fp);
  40. //don't forget to close!
  41. fclose(fp);
  42. }
  43. //calculates the position of the center of mass of the galaxy
  44. //IMPORTANT: THIS FUNCTION ASSUMES ALL STARS HAVE THE SAME MASS!
  45. point_t calculateCoM(RigidMass_t *stars, int nStars)
  46. {
  47. double totalX = 0;
  48. double totalY = 0;
  49. for(int i = 0; i < nStars; i++)
  50. {
  51. if(!isnan(stars[i].x)) totalX += stars[i].x;
  52. if(!isnan(stars[i].y)) totalY += stars[i].y;
  53. }
  54. point_t out;
  55. out.x = totalX / nStars;
  56. out.y = totalY / nStars;
  57. return out;
  58. }
  59. //calculates the velocity of the center of mass of a galaxy
  60. //IMPORTANT: THIS FUNCTION ASSUMES ALL STARS HAVE THE SAME MASS!
  61. point_t calculateCoV(RigidMass_t *stars, int nStars)
  62. {
  63. double totalVx = 0;
  64. double totalVy = 0;
  65. for(int i = 0; i < nStars; i++)
  66. {
  67. if(!isnan(stars[i].vx)) totalVx += stars[i].vx;
  68. if(!isnan(stars[i].vy)) totalVy += stars[i].vy;
  69. }
  70. point_t out;
  71. out.x = totalVx / nStars;
  72. out.y = totalVy / nStars;
  73. return out;
  74. }
  75. //Shifts a galaxy by a certain x, y, vx, and vy.
  76. //IMPORTANT: THIS FUNCTION ASSUMES ALL STARS HAVE THE SAME MASS!
  77. void shiftGalaxy(RigidMass_t *stars, int nStars, double dx, double dy, double dvx, double dvy)
  78. {
  79. for(int i = 0; i < nStars; i++)
  80. {
  81. stars[i].x += dx;
  82. stars[i].y += dy;
  83. stars[i].vx += dvx;
  84. stars[i].vy += dvy;
  85. }
  86. }
  87. void saveGalaxy(RigidMass_t *stars1, RigidMass_t *stars2,
  88. int n1, int n2,
  89. config_t conf1, char* filename)
  90. {
  91. RigidMass_t *all;
  92. all = malloc(sizeof(RigidMass_t) * (n1 + n2));
  93. memcpy(all, stars1, sizeof(RigidMass_t) * n1); //copy stars1 to all
  94. memcpy(&all[n1], stars2, sizeof(RigidMass_t) * n2); //stars2 to all
  95. conf1.nStars = n1 + n2;
  96. conf1.iteration = 0;
  97. FILE *fp;
  98. fp = fopen(filename, "w");
  99. fwrite(&conf1, sizeof(config_t), 1, fp);
  100. fwrite(all, sizeof(RigidMass_t), n1 + n2, fp);
  101. fclose(fp);
  102. }
  103. void prnHelp(char *name)
  104. {
  105. printf("Usage: %s [OPTIONS] SOURCE1 SOURCE2 DEST\r\n", name);
  106. printf("Available options:\r\n");
  107. printf("d ANG\t - Angle of collision (degrees)\r\n");
  108. printf("v VEL\t - Velocity of collision\r\n");
  109. exit(1);
  110. }
  111. //too lazy for arrays when there's only two elements in each one
  112. config_t conf1, conf2;
  113. RigidMass_t *stars1;
  114. RigidMass_t *stars2;
  115. int main(int argc, char **argv)
  116. {
  117. printf("\t\tStephen's Gravitational Engine\r\n");
  118. printf("\t\t\tCollision catalyzer\r\n");
  119. printf("\t\t\twww.scd31.com\r\n");
  120. double vel = 10; //velocity of both galaxies. (One galaxy will be vel/2)
  121. double angle = 90; //angle of the collision (degrees)
  122. int success = 0;
  123. char c;
  124. //do not process the last 3 arguments. those are the filenames
  125. while((c = getopt(argc - 3, argv, "d:v:")) != -1)
  126. {
  127. success = 1;
  128. switch(c)
  129. {
  130. case 'd':
  131. angle = atoi(optarg);
  132. break;
  133. case 'v':
  134. vel = atoi(optarg);
  135. break;
  136. default:
  137. prnHelp(argv[0]);
  138. }
  139. }
  140. if(0) //temporary
  141. {
  142. prnHelp(argv[0]);
  143. }
  144. //at this point, we know we can start working on the problem
  145. printf("Loading %s...\r\n", argv[argc - 3]);
  146. loadGalaxy(argv[argc - 3], &conf1, &stars1);
  147. printf("Loading %s...\r\n", argv[argc - 2]);
  148. loadGalaxy(argv[argc - 2], &conf2, &stars2);
  149. int d = 1000; //distance from galaxy to collision point
  150. int w = conf1.imgW;
  151. int h = conf1.imgH;
  152. double angleRad = 3.1415926535 * (0.5 - angle / 360);
  153. int dx = d * cos(angleRad);
  154. int dy = d * sin(angleRad);
  155. point_t pos1;
  156. pos1.x = w/2 + dx;
  157. pos1.y = h/2 - dy;
  158. point_t pos2;
  159. pos2.x = w/2 - dx;
  160. pos2.y = h/2 - dy;
  161. point_t vel1;
  162. vel1.x = -vel * cos(angleRad);
  163. vel1.y = vel * sin(angleRad);
  164. point_t vel2;
  165. vel2.x = vel * cos(angleRad);
  166. vel2.y = vel * sin(angleRad);
  167. //Galaxy 1
  168. point_t c1 = calculateCoM(stars1, conf1.nStars);
  169. point_t v1 = calculateCoV(stars1, conf1.nStars);
  170. printf("Galaxy 1 is at %f,%f moving at %f,%f\r\n", c1.x, c1.y, v1.x, v1.y);
  171. shiftGalaxy(stars1, conf1.nStars,
  172. pos1.x - c1.x, pos1.y - c1.y,
  173. vel1.x - v1.x, vel1.y - v1.y);
  174. //Galaxy 2
  175. //I regret not using arrays
  176. point_t c2 = calculateCoM(stars2, conf2.nStars);
  177. point_t v2 = calculateCoV(stars2, conf2.nStars);
  178. printf("Galaxy 2 is at %f,%f moving at %f,%f\r\n", c2.x, c2.y, v2.x, v2.y);
  179. shiftGalaxy(stars2, conf2.nStars,
  180. pos2.x - c2.x, pos2.y - c2.y,
  181. vel2.x - v2.x, vel2.y - v2.y);
  182. saveGalaxy(stars1, stars2,
  183. conf1.nStars, conf2.nStars,
  184. conf1, argv[argc - 1]);
  185. return 0;
  186. }