changed reading hint
[gromacs/adressmacs.git] / src / ngmx / highway.c
blob9ccdd779dc80db1e469c771fd6a825e9e19faf00
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 2.0
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * Please refer to:
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
23 * or e-mail to:
24 * gromacs@chem.rug.nl
26 * And Hey:
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_highway_c = "$Id$";
31 #include <stdio.h>
32 #include <math.h>
33 #include "futil.h"
34 #include "macros.h"
35 #include "smalloc.h"
36 #include "xutil.h"
37 #include "copyrite.h"
38 #include "statutil.h"
40 /* Units are meter and second */
42 typedef struct {
43 int id; /* Identification */
44 int x,xold;
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 */
53 } t_car;
55 typedef struct {
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 */
60 } t_input;
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" };
67 typedef struct {
68 int ncars;
69 t_car *cars;
70 t_input *ir;
71 int step;
72 bool bDriving; /* Are we driving ? */
73 bool bFog; /* Is it foggy ? */
74 t_windata main;
75 t_windata win;
76 t_windata but[NBUT];
77 } t_xhighway;
79 int read_cars(t_x11 *x11,char *fn,t_car **cars)
81 FILE *in;
82 int i,n;
83 char buf[100],b2[100];
84 t_car *c;
86 in=ffopen(fn,"r");
87 fscanf(in,"%d",&n);
88 snew(*cars,n);
90 for(i=0; (i<n); i++) {
91 c=&((*cars)[i]);
92 c->id=i;
93 c->lane=0;
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));
99 fclose(in);
101 return n;
104 t_input *read_input(char *fn)
106 FILE *in;
107 t_input *ir;
109 snew(ir,1);
110 in=ffopen(fn,"r");
112 fscanf(in,"%d %d %f %f",&ir->nlane,&ir->metres,&ir->dt,&ir->min_dist);
114 fclose(in);
115 return ir;
118 static float get_dist(int ncars,t_car cars[],int which,bool bFog,
119 int dir,int lane,int metres,int *nearest)
121 int i,near;
122 float dist,nd;
124 if (dir < 0)
125 dist=-metres;
126 else
127 dist=metres;
128 near=-1;
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))
134 nd+=metres;
135 else if ((nd > 0) && (dir < 0))
136 nd-=metres;
138 if (!bFog || (fabs(nd) < 50)) {
139 if (dir < 0) {
140 if (nd > dist) {
141 dist=nd;
142 near=i;
145 else if (dir > 0) {
146 if (nd < dist) {
147 dist=nd;
148 near=i;
153 *nearest=near;
154 return fabs(dist);
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))
178 cars[i].lane += 1;
179 else {
180 /* Use brakes */
181 cars[i].v -= cars[i].brake*ir->dt;
182 if (cars[i].v < 0)
183 cars[i].v = 0;
184 if (n_bef != -1)
185 if ((cars[i].v < cars[n_bef].v) && (dist > ir->min_dist/2))
186 cars[i].v=cars[n_bef].v;
187 cars[i].bBrake=TRUE;
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))
197 cars[i].lane -= 1;
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;
209 /* Detect Crashes */
210 /* Plot */
211 ExposeWin(x11->disp,xhw->win.self);
214 static void Configure(t_xhighway *xhw)
216 Window self;
217 int i,h,w,dh;
218 float dw;
220 dh=20;
221 h=xhw->main.height;
222 w=xhw->main.width;
223 dw=((float)(w-2))/NBUT-4;
224 for(i=0; (i<NBUT); i++) {
225 t_windata *wd=&(xhw->but[i]);
227 self=wd->self;
228 InitWin(wd,2+i*(dw+4),2,dw,dh,1,but_name[i]);
229 wd->self=self;
231 self=xhw->win.self;
232 InitWin(&xhw->win,2,dh+6,w-6,h-dh-10,1,xhw->main.text);
233 xhw->win.self=self;
236 static void draw_car(Display *disp,Window wd,GC gc,
237 t_car *car,int w0,int h0)
239 const int w=30;
240 const int h=14;
241 const int wr=10;
242 const int hr=8;
243 int j,w1,h1;
244 int jmax,hmax;
246 w1=w0-w / 2;
247 h1=h0-h / 2;
249 /* Carosserie */
250 XSetForeground(disp,gc,car->col);
251 XFillRectangle(disp,wd,gc,w1,h1,w,h);
253 /* Dak */
254 XSetForeground(disp,gc,car->roof);
255 XFillRectangle(disp,wd,gc,w0-wr/2,h0-hr/2,wr,hr);
257 /* Achterlicht */
258 if (car->bBrake) {
259 XSetForeground(disp,gc,YELLOW);
260 jmax=5;
261 hmax=5;
263 else {
264 XSetForeground(disp,gc,LIGHTRED);
265 jmax=3;
266 hmax=3;
268 for(j=1; (j<jmax); j++) {
269 int w11=w1-1-j;
270 int h11=h1-1;
271 XDrawLine(disp,wd,gc,w11,h11, w11,h11+hmax);
272 XDrawLine(disp,wd,gc,w11,h11+h-hmax,w11,h11+h);
275 /* Voorlicht */
276 XSetForeground(disp,gc,WHITE);
277 for(j=1; (j<3); j++) {
278 int w11=w1+w+j;
279 int h11=h1-1;
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)
287 t_xhighway *xhw;
288 t_windata *win;
289 float sx;
290 int i;
291 static int nyy=0;
292 static int *yy;
294 xhw = (t_xhighway *)data;
295 win = &(xhw->win);
297 if (nyy == 0) {
298 nyy=2*xhw->ir->nlane+1;
299 snew(yy,nyy);
301 for(i=0; (i<nyy); i++)
302 yy[i]=((float) i*win->height)/(nyy-1);
304 switch (event->type) {
305 case Expose: {
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]);
317 int w1=car->x*sx;
318 int h1=yy[1+2*(xhw->ir->nlane-1-car->lane)];
320 draw_car(x11->disp,win->self,x11->gc,car,w1,h1);
322 if (xhw->bDriving)
323 simulate(x11,xhw,xhw->ncars,xhw->cars,xhw->ir);
325 break;
327 case ConfigureNotify:
328 if (wd == xhw->main.self) {
329 xhw->main.width=event->xconfigure.width;
330 xhw->main.height=event->xconfigure.height;
331 Configure(xhw);
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;
343 break;
344 case ButtonPress:
345 return TRUE;
346 default:
347 break;
349 return FALSE;
352 static bool butCallBack(struct t_x11 *x11,XEvent *event, Window wd, void *data)
354 XSetWindowAttributes attr;
355 t_xhighway *xhw;
356 t_windata *win;
357 char *label;
358 int i;
360 xhw = (t_xhighway *)data;
361 for(i=0; (i<NBUT); i++) {
362 if (xhw->but[i].self == wd)
363 break;
365 if (i == NBUT) {
366 fprintf(stderr,"Incorrect window: %x in butcallback\n",(unsigned)wd);
367 return FALSE;
369 win=&(xhw->but[i]);
371 switch (event->type) {
372 case Expose:
373 XClearWindow(x11->disp,win->self);
374 switch (i) {
375 case StartStop:
376 label=Driving[xhw->bDriving];
377 break;
378 case Fog:
379 label=Fogs[xhw->bFog];
380 break;
381 default:
382 label=win->text;
384 XSetForeground(x11->disp,x11->gc,WHITE);
385 TextInWin(x11,win,label,eXCenter,eYCenter);
386 break;
388 case ConfigureNotify:
389 win->width=event->xconfigure.width;
390 win->height=event->xconfigure.height;
391 break;
392 case ButtonPress:
393 switch (i) {
394 case Quit:
395 return TRUE;
396 case StartStop:
397 xhw->bDriving=1-xhw->bDriving;
398 ExposeWin(x11->disp,win->self);
399 if (xhw->bDriving)
400 ExposeWin(x11->disp,xhw->win.self);
401 break;
402 case Fog:
403 xhw->bFog=1-xhw->bFog;
404 if (xhw->bFog)
405 attr.background_pixel=DARKGREY;
406 else
407 attr.background_pixel=BLACK;
408 XChangeWindowAttributes(x11->disp,xhw->win.self,CWBackPixel,&attr);
409 /*ExposeWin(x11->disp,win->self);*/
410 break;
411 default:
412 break;
414 break;
415 default:
416 break;
418 return FALSE;
421 t_xhighway *GetXHW(t_x11 *x11,char *infile,char *carfile)
423 t_xhighway *xhw;
424 int i,h,dh,w;
426 snew(xhw,1);
428 xhw->ir=read_input(infile);
429 xhw->ncars=read_cars(x11,carfile,&(xhw->cars));
431 h=xhw->ir->nlane*40;
432 dh=20;
433 w=752;
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);
443 Configure(xhw);
445 for(i=0; (i<NBUT); i++) {
446 t_windata *wd=&(xhw->but[i]);
448 wd->self=XCreateSimpleWindow(x11->disp,xhw->main.self,
449 wd->x,wd->y,
450 wd->width,wd->height,
451 wd->bwidth,WHITE,BLACK);
452 x11->RegisterCallback(x11,wd->self,xhw->main.self,
453 butCallBack,xhw);
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);
466 return xhw;
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"
477 t_x11 *x11;
478 t_xhighway *xhw;
479 t_filenm fnm[] = {
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");
492 exit(1);
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);
498 x11->MainLoop(x11);
499 x11->CleanUp(x11);
501 thanx(stdout);
503 return 0;