/
main_rec.c
205 lines (161 loc) · 5.27 KB
/
main_rec.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "star.h"
#ifdef ANIMATE
#include <X11/Xlib.h>
#include <X11/Xutil.h>
//Size of the window
#define X_SIZE 800
#define Y_SIZE 800
#endif
#define prec float
#define PI 3.14159265359
#define G 1
//Delta time
static prec gdt = 0.3;
static void update_position(struct star* str, prec time_unit)
{
prec xacc = readXForce(str) / readMass(str);
prec xSpeedIncrease = xacc * time_unit;
prec yacc = readYForce(str) / readMass(str);
prec ySpeedIncrease = yacc * time_unit;
prec newXSpeed = readXSpeed(str) + xSpeedIncrease;
prec newYSpeed = readYSpeed(str) + ySpeedIncrease;
newSpeed(str, newXSpeed, newYSpeed);
prec xPosIncrease = readXSpeed(str) * time_unit + yacc * pow(time_unit, 2.0)/2;
prec yPosIncrease = readYSpeed(str) * time_unit + yacc * pow(time_unit, 2.0)/2;
prec newXPos = readXPos(str) + xPosIncrease;
prec newYPos = readYPos(str) + yPosIncrease;
newPos(str, newXPos, newYPos);
}
static void resetForce(struct star* str) {
newForce(str, 0, 0);
}
static void addForce(struct star* star_A, struct star* star_B)
{
prec dx = readXPos(star_A) - readXPos(star_B);
prec dy = readYPos(star_A) - readYPos(star_B);
prec distance = (double)sqrt(pow(dx, 2.0) + pow(dy, 2.0));
prec force = (prec)(G * (double)readMass(star_A) * (double)readMass(star_B) / distance);
prec fx = force * dx / distance;
prec fy = force * dy / distance;
prec newXForceA = readXForce(star_A) - fx;
prec newXForceB = readXForce(star_B) + fx;
prec newYForceA = readYForce(star_A) - fy;
prec newYForceB = readYForce(star_B) + fy;
newForce(star_A, newXForceA, newYForceA);
newForce(star_B, newXForceB, newYForceB);
}
// Generates a pseudo-random number in the interval 0 to 1
static prec newRand()
{
prec r = (prec)((double)rand()/(double)RAND_MAX);
return r;
}
void generate_init_values(int number_of_stars, struct star* star_array)
{
time_t t;
srand((unsigned) time(&t));
for(int i = 0; i < number_of_stars; ++i){
star_array[i] = makeStar();
prec angle = 360 * newRand();
prec radius = 100 * newRand();
newPos(&star_array[i], radius * cos(angle) + 350, 0.5 * radius * sin(angle) + 350);
newSpeed(&star_array[i], 0.4*(star_array[i].ypos - 350), (-0.4)*(star_array[i].xpos - 350));
newMass(&star_array[i], 2*newRand() + 2);
}
}
static void resetForces(int number_of_stars, struct star* star_array)
{
for(int i = 0; i < number_of_stars; ++i){
resetForce(&star_array[i]);
}
}
static void updateForces(int firstStar, int secondStar, struct star* star_array)
{
if (firstStar > 0){
if (secondStar > 1){
addForce(&star_array[firstStar],&star_array[secondStar]);
updateForces(firstStar, secondStar - 1, star_array);
}else{
updateForces(firstStar - 1, firstStar - 2, star_array);
}
}
}
// Manually copy coordinates from stars into points (to be drawn).
// Look at the manual file for XPoint to see which
// format XPoint accepts its coordinates in.
#ifdef ANIMATE
static void copyToXBuffer(struct star* star_array, XPoint* points, int number_of_stars)
{
for(int i = 0; i < number_of_stars; ++i){
points[i].x = readXPos(&star_array[i]);
points[i].y = readYPos(&star_array[i]);
}
}
#endif
int main(int argc, char* argv[]) {
int number_of_stars = 200;
int iterations = 1000;
prec time_unit = gdt;
if(argc == 3)
{
number_of_stars = atoi(argv[1]);
iterations = atoi(argv[2]);
}
struct star* star_array = malloc(sizeof(struct star) * number_of_stars);
generate_init_values(number_of_stars, star_array);
#ifdef ANIMATE
XPoint* points = malloc(sizeof(XPoint)*number_of_stars);
Display* disp;
Window window, rootwin;
int screen;
disp = XOpenDisplay(NULL);
screen = DefaultScreen(disp);
rootwin = RootWindow(disp,screen);
window = XCreateSimpleWindow(disp,rootwin,
0,0,X_SIZE,Y_SIZE,1,0,0);
GC gc = XCreateGC(disp, window, 0, 0);
XSetForeground(disp, gc, WhitePixel(disp, screen));
XSetBackground(disp, gc, BlackPixel(disp, screen));
XMapWindow(disp,window);
XClearWindow(disp,window);
copyToXBuffer(star_array, points, number_of_stars);
XDrawPoints(disp, window, gc, points, number_of_stars, 0);
XFlush(disp);
#endif
clock_t start = clock();
for(int i = 0; i < iterations; i++)
{
#ifndef ANIMATE
resetForces(number_of_stars, star_array);
updateForces(number_of_stars, number_of_stars - 1, star_array);
for(int j = 0; j < number_of_stars; ++j){
update_position(&star_array[j], time_unit);
}
#endif
#ifdef ANIMATE
resetForces(number_of_stars, star_array);
updateForces(number_of_stars, number_of_stars - 1, star_array);
for(int j = 0; j < number_of_stars; ++j){
update_position(&star_array[j], time_unit);
copyToXBuffer(star_array, points,number_of_stars );
XDrawPoints(disp, window, gc, points, number_of_stars, CoordModeOrigin);
}
XClearWindow(disp,window);
#endif
}
clock_t stop = clock();
float diff = (float)(stop - start)/CLOCKS_PER_SEC;
printf("Total: %lf seconds\n",diff);
printf("Bodies: %d\n",number_of_stars);
printf("Iterations: %d\n", iterations);
#ifdef ANIMATE
free(points);
XCloseDisplay(disp);
#endif
free(star_array);
return 0;
}