4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_highway_c
= "$Id$";
40 /* Units are meter and second */
43 int id
; /* Identification */
45 float v
; /* Position and velocity */
46 float vwanted
; /* Wants to drive at this speed */
47 float acc
; /* Acceleration */
48 float brake
; /* Break */
49 int lane
,oldlane
; /* Currently in lane */
50 bool bBrake
; /* Currently on the brakes */
51 unsigned long col
; /* Colour */
52 unsigned long roof
; /* Roof Colour */
56 int nlane
; /* Number of lanes on highway */
57 int metres
; /* Road length */
58 float dt
; /* Time step */
59 float min_dist
; /* Min distance cars can come */
62 static char *Driving
[] = { "Start","Stop" };
63 static char *Fogs
[] = { "Fog", "No Fog" };
64 enum buttons
{ Quit
, StartStop
, Fog
, NBUT
};
65 static char *but_name
[NBUT
] = { "Quit", "Start", "Fog" };
72 bool bDriving
; /* Are we driving ? */
73 bool bFog
; /* Is it foggy ? */
79 int read_cars(t_x11
*x11
,char *fn
,t_car
**cars
)
83 char buf
[100],b2
[100];
90 for(i
=0; (i
<n
); i
++) {
94 fscanf(in
,"%d %f %f %f %f %s %s",
95 &(c
->x
),&(c
->v
),&(c
->vwanted
),&(c
->acc
),&(c
->brake
),buf
,b2
);
96 x11
->GetNamedColor(x11
,buf
,&(c
->col
));
97 x11
->GetNamedColor(x11
,b2
,&(c
->roof
));
104 t_input
*read_input(char *fn
)
112 fscanf(in
,"%d %d %f %f",&ir
->nlane
,&ir
->metres
,&ir
->dt
,&ir
->min_dist
);
118 static float get_dist(int ncars
,t_car cars
[],int which
,bool bFog
,
119 int dir
,int lane
,int metres
,int *nearest
)
130 for(i
=0; (i
<ncars
); i
++)
131 if ((i
!= which
) && (cars
[i
].oldlane
== lane
)){
132 nd
=cars
[i
].xold
-cars
[which
].xold
;
133 if ((nd
< 0) && (dir
> 0))
135 else if ((nd
> 0) && (dir
< 0))
138 if (!bFog
|| (fabs(nd
) < 50)) {
157 void simulate(t_x11
*x11
,t_xhighway
*xhw
,
158 int ncars
,t_car cars
[],t_input
*ir
)
160 int i
,n_bef
,n_bef1
,n_beh
;
161 float dist
,distf
,distb
;
163 for(i
=0; (i
<ncars
); i
++) {
164 cars
[i
].xold
=cars
[i
].x
;
165 cars
[i
].oldlane
=cars
[i
].lane
;
167 for(i
=0; (i
<ncars
); i
++) {
168 cars
[i
].bBrake
=FALSE
;
169 dist
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
170 1,cars
[i
].lane
,ir
->metres
,&n_bef
);
171 if (dist
< ir
->min_dist
) {
172 distf
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
173 1,cars
[i
].lane
+1,ir
->metres
,&n_bef1
);
174 distb
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
175 -1,cars
[i
].lane
+1,ir
->metres
,&n_beh
);
176 if ((cars
[i
].lane
< ir
->nlane
-1) && (distb
>= ir
->min_dist
) &&
177 (distf
>= ir
->min_dist
))
181 cars
[i
].v
-= cars
[i
].brake
*ir
->dt
;
185 if ((cars
[i
].v
< cars
[n_bef
].v
) && (dist
> ir
->min_dist
/2))
186 cars
[i
].v
=cars
[n_bef
].v
;
190 else if ((cars
[i
].lane
> 0) && (cars
[i
].v
== cars
[i
].vwanted
)) {
191 /* Check if I can go right again */
192 dist
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
193 1,cars
[i
].lane
-1,ir
->metres
,&n_bef
);
194 distb
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
195 -1,cars
[i
].lane
-1,ir
->metres
,&n_beh
);
196 if ((dist
>= ir
->min_dist
) && (distb
>= ir
->min_dist
))
200 cars
[i
].x
+= cars
[i
].v
*ir
->dt
;
201 if (cars
[i
].x
> ir
->metres
)
202 cars
[i
].x
-= ir
->metres
;
203 if (!cars
[i
].bBrake
&& (cars
[i
].v
< cars
[i
].vwanted
)) {
204 cars
[i
].v
+= cars
[i
].acc
*ir
->dt
;
205 if (cars
[i
].v
> cars
[i
].vwanted
)
206 cars
[i
].v
= cars
[i
].vwanted
;
211 ExposeWin(x11
->disp
,xhw
->win
.self
);
214 static void Configure(t_xhighway
*xhw
)
223 dw
=((float)(w
-2))/NBUT
-4;
224 for(i
=0; (i
<NBUT
); i
++) {
225 t_windata
*wd
=&(xhw
->but
[i
]);
228 InitWin(wd
,2+i
*(dw
+4),2,dw
,dh
,1,but_name
[i
]);
232 InitWin(&xhw
->win
,2,dh
+6,w
-6,h
-dh
-10,1,xhw
->main
.text
);
236 static void draw_car(Display
*disp
,Window wd
,GC gc
,
237 t_car
*car
,int w0
,int h0
)
250 XSetForeground(disp
,gc
,car
->col
);
251 XFillRectangle(disp
,wd
,gc
,w1
,h1
,w
,h
);
254 XSetForeground(disp
,gc
,car
->roof
);
255 XFillRectangle(disp
,wd
,gc
,w0
-wr
/2,h0
-hr
/2,wr
,hr
);
259 XSetForeground(disp
,gc
,YELLOW
);
264 XSetForeground(disp
,gc
,LIGHTRED
);
268 for(j
=1; (j
<jmax
); j
++) {
271 XDrawLine(disp
,wd
,gc
,w11
,h11
, w11
,h11
+hmax
);
272 XDrawLine(disp
,wd
,gc
,w11
,h11
+h
-hmax
,w11
,h11
+h
);
276 XSetForeground(disp
,gc
,WHITE
);
277 for(j
=1; (j
<3); j
++) {
280 XDrawLine(disp
,wd
,gc
,w11
,h11
, w11
,h11
+3);
281 XDrawLine(disp
,wd
,gc
,w11
,h11
+h
-3,w11
,h11
+h
);
285 static bool xhwCallBack(struct t_x11
*x11
,XEvent
*event
, Window wd
, void *data
)
294 xhw
= (t_xhighway
*)data
;
298 nyy
=2*xhw
->ir
->nlane
+1;
301 for(i
=0; (i
<nyy
); i
++)
302 yy
[i
]=((float) i
*win
->height
)/(nyy
-1);
304 switch (event
->type
) {
306 if (wd
== win
->self
) {
307 sx
=(float)win
->width
/ xhw
->ir
->metres
;
309 XClearWindow(x11
->disp
,win
->self
);
310 XSetForeground(x11
->disp
,x11
->gc
,WHITE
);
312 for(i
=2; (i
<nyy
-1); i
+=2)
313 XDrawLine(x11
->disp
,win
->self
,x11
->gc
,0,yy
[i
],win
->width
-1,yy
[i
]);
315 for(i
=0; (i
<xhw
->ncars
); i
++) {
316 t_car
*car
=&(xhw
->cars
[i
]);
318 int h1
=yy
[1+2*(xhw
->ir
->nlane
-1-car
->lane
)];
320 draw_car(x11
->disp
,win
->self
,x11
->gc
,car
,w1
,h1
);
323 simulate(x11
,xhw
,xhw
->ncars
,xhw
->cars
,xhw
->ir
);
327 case ConfigureNotify
:
328 if (wd
== xhw
->main
.self
) {
329 xhw
->main
.width
=event
->xconfigure
.width
;
330 xhw
->main
.height
=event
->xconfigure
.height
;
332 for(i
=0; (i
<NBUT
); i
++)
333 XMoveResizeWindow(x11
->disp
,xhw
->but
[i
].self
,
334 xhw
->but
[i
].x
,xhw
->but
[i
].y
,
335 xhw
->but
[i
].width
,xhw
->but
[i
].height
);
336 XMoveResizeWindow(x11
->disp
,win
->self
,
337 win
->x
,win
->y
,win
->width
,win
->height
);
339 else if (wd
== win
->self
) {
340 win
->width
=event
->xconfigure
.width
;
341 win
->height
=event
->xconfigure
.height
;
352 static bool butCallBack(struct t_x11
*x11
,XEvent
*event
, Window wd
, void *data
)
354 XSetWindowAttributes attr
;
360 xhw
= (t_xhighway
*)data
;
361 for(i
=0; (i
<NBUT
); i
++) {
362 if (xhw
->but
[i
].self
== wd
)
366 fprintf(stderr
,"Incorrect window: %x in butcallback\n",(unsigned)wd
);
371 switch (event
->type
) {
373 XClearWindow(x11
->disp
,win
->self
);
376 label
=Driving
[xhw
->bDriving
];
379 label
=Fogs
[xhw
->bFog
];
384 XSetForeground(x11
->disp
,x11
->gc
,WHITE
);
385 TextInWin(x11
,win
,label
,eXCenter
,eYCenter
);
388 case ConfigureNotify
:
389 win
->width
=event
->xconfigure
.width
;
390 win
->height
=event
->xconfigure
.height
;
397 xhw
->bDriving
=1-xhw
->bDriving
;
398 ExposeWin(x11
->disp
,win
->self
);
400 ExposeWin(x11
->disp
,xhw
->win
.self
);
403 xhw
->bFog
=1-xhw
->bFog
;
405 attr
.background_pixel
=DARKGREY
;
407 attr
.background_pixel
=BLACK
;
408 XChangeWindowAttributes(x11
->disp
,xhw
->win
.self
,CWBackPixel
,&attr
);
409 /*ExposeWin(x11->disp,win->self);*/
421 t_xhighway
*GetXHW(t_x11
*x11
,char *infile
,char *carfile
)
428 xhw
->ir
=read_input(infile
);
429 xhw
->ncars
=read_cars(x11
,carfile
,&(xhw
->cars
));
434 InitWin(&xhw
->main
,0,0,w
,h
+dh
+7,1,Program());
435 xhw
->main
.self
=XCreateSimpleWindow(x11
->disp
,x11
->root
,
436 xhw
->main
.x
,xhw
->main
.y
,
437 xhw
->main
.width
,xhw
->main
.height
,
438 xhw
->main
.bwidth
,WHITE
,BLACK
);
439 x11
->RegisterCallback(x11
,xhw
->main
.self
,0,xhwCallBack
,xhw
);
440 x11
->SetInputMask(x11
,xhw
->main
.self
,ButtonPressMask
| ExposureMask
|
441 StructureNotifyMask
);
445 for(i
=0; (i
<NBUT
); i
++) {
446 t_windata
*wd
=&(xhw
->but
[i
]);
448 wd
->self
=XCreateSimpleWindow(x11
->disp
,xhw
->main
.self
,
450 wd
->width
,wd
->height
,
451 wd
->bwidth
,WHITE
,BLACK
);
452 x11
->RegisterCallback(x11
,wd
->self
,xhw
->main
.self
,
454 x11
->SetInputMask(x11
,wd
->self
,ButtonPressMask
| ExposureMask
|
455 StructureNotifyMask
);
458 xhw
->win
.self
=XCreateSimpleWindow(x11
->disp
,xhw
->main
.self
,
459 xhw
->win
.x
,xhw
->win
.y
,
460 xhw
->win
.width
,xhw
->win
.height
,
461 xhw
->win
.bwidth
,WHITE
,BLACK
);
462 x11
->RegisterCallback(x11
,xhw
->win
.self
,0,xhwCallBack
,xhw
);
463 x11
->SetInputMask(x11
,xhw
->win
.self
,ButtonPressMask
| ExposureMask
|
464 StructureNotifyMask
);
469 int main(int argc
,char *argv
[])
471 static char *desc
[] = {
472 "highway is the gromacs highway simulator. It is an X-windows",
473 "gadget that shows a (periodic) autobahn with a user defined",
474 "number of cars. Fog can be turned on or off to increase the",
475 "number of crashes. Nice for a background CPU-eater"
480 { efDAT
, "-f", "highway", ffREAD
},
481 { efDAT
, "-a", "auto", ffREAD
}
483 #define NFILE asize(fnm)
485 CopyRight(stdout
,argv
[0]);
486 parse_common_args(&argc
,argv
,PCA_CAN_TIME
,FALSE
,NFILE
,fnm
,
487 0,NULL
,asize(desc
),desc
,0,NULL
);
489 if ((x11
=GetX11(&argc
,argv
))==NULL
) {
490 fprintf(stderr
,"Can't connect to X Server.\n"
491 "Check your DISPLAY environment variable\n");
494 xhw
=GetXHW(x11
,opt2fn("-f",NFILE
,fnm
),opt2fn("-a",NFILE
,fnm
));
496 XMapWindow(x11
->disp
,xhw
->main
.self
);
497 XMapSubwindows(x11
->disp
,xhw
->main
.self
);