Added a few files to fix the build system.
[gromacs/rigid-bodies.git] / src / ngmx / g_highway.c
bloba81050dcc2086e9b49e6232ef8c91f541a67487d
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Gyas ROwers Mature At Cryogenic Speed
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <stdio.h>
40 #include <string.h>
41 #include <math.h>
42 #include "futil.h"
43 #include "macros.h"
44 #include "smalloc.h"
45 #include "xutil.h"
46 #include "copyrite.h"
47 #include "statutil.h"
48 #include "gmx_fatal.h"
50 /* Units are meter and second */
52 typedef struct {
53 int id; /* Identification */
54 float x,xold;
55 float v; /* Position and velocity */
56 float vwanted; /* Wants to drive at this speed */
57 float acc; /* Acceleration */
58 float brake; /* Break */
59 int lane,oldlane; /* Currently in lane */
60 gmx_bool bBrake; /* Currently on the brakes */
61 unsigned long col; /* Colour */
62 unsigned long roof; /* Roof Colour */
63 } t_car;
65 typedef struct {
66 int nlane; /* Number of lanes on highway */
67 int metres; /* Road length */
68 float dt; /* Time step */
69 float min_dist; /* Min distance cars can come */
70 int sleep; /* How long to sleep in between updates */
71 } t_input;
73 static const char *Driving[] = { "Start","Stop" };
74 static const char *Fogs[] = { "Fog", "No Fog" };
75 enum buttons { Quit, StartStop, Fog, NBUT };
76 static const char *but_name[NBUT] = { "Quit", "Start", "Fog" };
78 typedef struct {
79 int ncars;
80 t_car *cars;
81 t_input ir;
82 int step;
83 gmx_bool bDriving; /* Are we driving ? */
84 gmx_bool bFog; /* Is it foggy ? */
85 t_windata main;
86 t_windata win;
87 t_windata but[NBUT];
88 } t_xhighway;
90 int read_input(t_x11 *x11,const char *fn,t_car **cars,t_input *ir)
92 FILE *in;
93 int i,n;
94 char buf[100],b2[100];
95 t_car *c;
97 in=ffopen(fn,"r");
98 if (fscanf(in,"%d %d %f %f %d",
99 &ir->nlane,&ir->metres,&ir->dt,&ir->min_dist,&ir->sleep) != 5)
100 gmx_fatal(FARGS,"Not enough parameters in %s line 1",fn);
101 if (fscanf(in,"%d",&n) != 1)
102 gmx_fatal(FARGS,"Not enough parameters in %s line 2",fn);
103 snew(*cars,n);
105 for(i=0; (i<n); i++) {
106 c=&((*cars)[i]);
107 c->id=i;
108 c->lane=0;
109 if (fscanf(in,"%f %f %f %f %f %s %s",&(c->x),&(c->v),&(c->vwanted),
110 &(c->acc),&(c->brake),buf,b2) != 7)
111 gmx_fatal(FARGS,"Not enough parameters in %s line %d",fn,3+i);
112 x11->GetNamedColor(x11,buf,&(c->col));
113 x11->GetNamedColor(x11,b2,&(c->roof));
115 ffclose(in);
117 return n;
120 static float get_dist(int ncars,t_car cars[],int which,gmx_bool bFog,
121 int dir,int lane,int metres,int *nearest)
123 int i,near;
124 float dist,nd;
126 if (dir < 0)
127 dist=-metres;
128 else
129 dist=metres;
130 near=-1;
132 for(i=0; (i<ncars); i++)
133 if ((i != which) && (cars[i].oldlane == lane)){
134 nd=cars[i].xold-cars[which].xold;
135 if ((nd < 0) && (dir > 0))
136 nd+=metres;
137 else if ((nd > 0) && (dir < 0))
138 nd-=metres;
140 if (!bFog || (fabs(nd) < 50)) {
141 if (dir < 0) {
142 if (nd > dist) {
143 dist=nd;
144 near=i;
147 else if (dir > 0) {
148 if (nd < dist) {
149 dist=nd;
150 near=i;
155 *nearest=near;
156 return fabs(dist);
159 void simulate(t_x11 *x11,t_xhighway *xhw,
160 int ncars,t_car cars[],t_input *ir)
162 int i,n_bef,n_bef1,n_beh;
163 float dist,distf,distb;
165 for(i=0; (i<ncars); i++) {
166 cars[i].xold=cars[i].x;
167 cars[i].oldlane=cars[i].lane;
169 for(i=0; (i<ncars); i++) {
170 cars[i].bBrake=FALSE;
171 dist=get_dist(ncars,cars,i,xhw->bFog,
172 1,cars[i].lane,ir->metres,&n_bef);
173 if (dist < ir->min_dist) {
174 distf=get_dist(ncars,cars,i,xhw->bFog,
175 1,cars[i].lane+1,ir->metres,&n_bef1);
176 distb=get_dist(ncars,cars,i,xhw->bFog,
177 -1,cars[i].lane+1,ir->metres,&n_beh);
178 if ((cars[i].lane < ir->nlane-1) && (distb >= ir->min_dist) &&
179 (distf >= ir->min_dist))
180 cars[i].lane += 1;
181 else {
182 /* Use brakes */
183 cars[i].v -= cars[i].brake*ir->dt;
184 if (cars[i].v < 0)
185 cars[i].v = 0;
186 if (n_bef != -1)
187 if ((cars[i].v < cars[n_bef].v) && (dist > ir->min_dist/2))
188 cars[i].v=cars[n_bef].v;
189 cars[i].bBrake=TRUE;
192 else if ((cars[i].lane > 0) && (cars[i].v == cars[i].vwanted)) {
193 /* Check if I can go right again */
194 dist=get_dist(ncars,cars,i,xhw->bFog,
195 1,cars[i].lane-1,ir->metres,&n_bef);
196 distb=get_dist(ncars,cars,i,xhw->bFog,
197 -1,cars[i].lane-1,ir->metres,&n_beh);
198 if ((dist >= ir->min_dist) && (distb >= ir->min_dist))
199 cars[i].lane -= 1;
202 cars[i].x += cars[i].v*ir->dt;
203 if (cars[i].x > ir->metres)
204 cars[i].x -= ir->metres;
205 if (!cars[i].bBrake && (cars[i].v < cars[i].vwanted)) {
206 cars[i].v += cars[i].acc*ir->dt;
207 if (cars[i].v > cars[i].vwanted)
208 cars[i].v = cars[i].vwanted;
211 /* Detect Crashes */
212 /* Plot */
213 usleep(xhw->ir.sleep);
214 ExposeWin(x11->disp,xhw->win.self);
217 static void Configure(t_xhighway *xhw)
219 Window self;
220 int i,h,w,dh;
221 float dw;
223 dh=20;
224 h=xhw->main.height;
225 w=xhw->main.width;
226 dw=((float)(w-2))/NBUT-4;
227 for(i=0; (i<NBUT); i++) {
228 t_windata *wd=&(xhw->but[i]);
230 self=wd->self;
231 InitWin(wd,2+i*(dw+4),2,dw,dh,1,but_name[i]);
232 wd->self=self;
234 self=xhw->win.self;
235 InitWin(&xhw->win,2,dh+6,w-6,h-dh-10,1,xhw->main.text);
236 xhw->win.self=self;
239 static void draw_car(Display *disp,Window wd,GC gc,
240 t_car *car,int w0,int h0)
242 const int w=30;
243 const int h=14;
244 const int wr=10;
245 const int hr=8;
246 int j,w1,h1;
247 int jmax,hmax;
249 w1=w0-w / 2;
250 h1=h0-h / 2;
252 /* Carosserie */
253 XSetForeground(disp,gc,car->col);
254 XFillRectangle(disp,wd,gc,w1,h1,w,h);
256 /* Dak */
257 XSetForeground(disp,gc,car->roof);
258 XFillRectangle(disp,wd,gc,w0-wr/2,h0-hr/2,wr,hr);
260 /* Achterlicht */
261 if (car->bBrake) {
262 XSetForeground(disp,gc,YELLOW);
263 jmax=5;
264 hmax=5;
266 else {
267 XSetForeground(disp,gc,LIGHTRED);
268 jmax=3;
269 hmax=3;
271 for(j=1; (j<jmax); j++) {
272 int w11=w1-1-j;
273 int h11=h1-1;
274 XDrawLine(disp,wd,gc,w11,h11, w11,h11+hmax);
275 XDrawLine(disp,wd,gc,w11,h11+h-hmax,w11,h11+h);
278 /* Voorlicht */
279 XSetForeground(disp,gc,WHITE);
280 for(j=1; (j<3); j++) {
281 int w11=w1+w+j;
282 int h11=h1-1;
283 XDrawLine(disp,wd,gc,w11,h11, w11,h11+3);
284 XDrawLine(disp,wd,gc,w11,h11+h-3,w11,h11+h);
288 static gmx_bool xhwCallBack(struct t_x11 *x11,XEvent *event, Window wd, void *data)
290 t_xhighway *xhw;
291 t_windata *win;
292 float sx;
293 int i;
294 static int nyy=0;
295 static int *yy;
297 xhw = (t_xhighway *)data;
298 win = &(xhw->win);
300 if (nyy == 0) {
301 nyy=2*xhw->ir.nlane+1;
302 snew(yy,nyy);
304 for(i=0; (i<nyy); i++)
305 yy[i]=((float) i*win->height)/(nyy-1);
307 switch (event->type) {
308 case Expose: {
309 if (wd == win->self) {
310 sx=(float)win->width / xhw->ir.metres;
312 XClearWindow(x11->disp,win->self);
313 XSetForeground(x11->disp,x11->gc,WHITE);
315 for(i=2; (i<nyy-1); i+=2)
316 XDrawLine(x11->disp,win->self,x11->gc,0,yy[i],win->width-1,yy[i]);
318 for(i=0; (i<xhw->ncars); i++) {
319 t_car *car=&(xhw->cars[i]);
320 int w1=car->x*sx;
321 int h1=yy[1+2*(xhw->ir.nlane-1-car->lane)];
323 draw_car(x11->disp,win->self,x11->gc,car,w1,h1);
325 if (xhw->bDriving)
326 simulate(x11,xhw,xhw->ncars,xhw->cars,&xhw->ir);
328 break;
330 case ConfigureNotify:
331 if (wd == xhw->main.self) {
332 xhw->main.width=event->xconfigure.width;
333 xhw->main.height=event->xconfigure.height;
334 Configure(xhw);
335 for(i=0; (i<NBUT); i++)
336 XMoveResizeWindow(x11->disp,xhw->but[i].self,
337 xhw->but[i].x,xhw->but[i].y,
338 xhw->but[i].width,xhw->but[i].height);
339 XMoveResizeWindow(x11->disp,win->self,
340 win->x,win->y,win->width,win->height);
342 else if (wd == win->self) {
343 win->width=event->xconfigure.width;
344 win->height=event->xconfigure.height;
346 break;
347 case ButtonPress:
348 return TRUE;
349 default:
350 break;
352 return FALSE;
355 static gmx_bool butCallBack(struct t_x11 *x11,XEvent *event, Window wd, void *data)
357 XSetWindowAttributes attr;
358 t_xhighway *xhw;
359 t_windata *win;
360 const char *label;
361 int i;
363 xhw = (t_xhighway *)data;
364 for(i=0; (i<NBUT); i++) {
365 if (xhw->but[i].self == wd)
366 break;
368 if (i == NBUT) {
369 fprintf(stderr,"Incorrect window: %x in butcallback\n",(unsigned)wd);
370 return FALSE;
372 win=&(xhw->but[i]);
374 switch (event->type) {
375 case Expose:
376 XClearWindow(x11->disp,win->self);
377 switch (i) {
378 case StartStop:
379 label=Driving[xhw->bDriving];
380 break;
381 case Fog:
382 label=Fogs[xhw->bFog];
383 break;
384 default:
385 label=win->text;
387 XSetForeground(x11->disp,x11->gc,WHITE);
388 TextInWin(x11,win,label,eXCenter,eYCenter);
389 break;
391 case ConfigureNotify:
392 win->width=event->xconfigure.width;
393 win->height=event->xconfigure.height;
394 break;
395 case ButtonPress:
396 switch (i) {
397 case Quit:
398 return TRUE;
399 case StartStop:
400 xhw->bDriving=1-xhw->bDriving;
401 ExposeWin(x11->disp,win->self);
402 if (xhw->bDriving)
403 ExposeWin(x11->disp,xhw->win.self);
404 break;
405 case Fog:
406 xhw->bFog=1-xhw->bFog;
407 if (xhw->bFog)
408 attr.background_pixel=DARKGREY;
409 else
410 attr.background_pixel=BLACK;
411 XChangeWindowAttributes(x11->disp,xhw->win.self,CWBackPixel,&attr);
412 /*ExposeWin(x11->disp,win->self);*/
413 break;
414 default:
415 break;
417 break;
418 default:
419 break;
421 return FALSE;
424 t_xhighway *GetXHW(t_x11 *x11,const char *infile)
426 t_xhighway *xhw;
427 int i,h,dh,w;
428 char progname[STRLEN];
430 snew(xhw,1);
431 xhw->ncars=read_input(x11,infile,&(xhw->cars),&xhw->ir);
433 h=xhw->ir.nlane*40;
434 dh=20;
435 w=752;
436 strncpy(progname,Program(),STRLEN-1);
437 InitWin(&xhw->main,0,0,w,h+dh+7,1,progname);
438 xhw->main.self=XCreateSimpleWindow(x11->disp,x11->root,
439 xhw->main.x,xhw->main.y,
440 xhw->main.width,xhw->main.height,
441 xhw->main.bwidth,WHITE,BLACK);
442 x11->RegisterCallback(x11,xhw->main.self,0,xhwCallBack,xhw);
443 x11->SetInputMask(x11,xhw->main.self,ButtonPressMask | ExposureMask |
444 StructureNotifyMask);
446 Configure(xhw);
448 for(i=0; (i<NBUT); i++) {
449 t_windata *wd=&(xhw->but[i]);
451 wd->self=XCreateSimpleWindow(x11->disp,xhw->main.self,
452 wd->x,wd->y,
453 wd->width,wd->height,
454 wd->bwidth,WHITE,BLACK);
455 x11->RegisterCallback(x11,wd->self,xhw->main.self,
456 butCallBack,xhw);
457 x11->SetInputMask(x11,wd->self,ButtonPressMask | ExposureMask |
458 StructureNotifyMask);
461 xhw->win.self=XCreateSimpleWindow(x11->disp,xhw->main.self,
462 xhw->win.x,xhw->win.y,
463 xhw->win.width,xhw->win.height,
464 xhw->win.bwidth,WHITE,BLACK);
465 x11->RegisterCallback(x11,xhw->win.self,0,xhwCallBack,xhw);
466 x11->SetInputMask(x11,xhw->win.self,ButtonPressMask | ExposureMask |
467 StructureNotifyMask);
469 return xhw;
472 int main(int argc,char *argv[])
474 const char *desc[] = {
475 "[TT]highway[tt] is the GROMCAS highway simulator. It is an X-windows",
476 "gadget that shows a (periodic) Autobahn with a user defined",
477 "number of cars. Fog can be turned on or off to increase the",
478 "number of crashes. Nice for a background CPU-eater. A sample",
479 "input file is in [TT]$GMXDATA/top/highway.dat[tt]"
481 output_env_t oenv;
482 t_x11 *x11;
483 t_xhighway *xhw;
484 t_filenm fnm[] = {
485 { efDAT, "-f", "highway", ffREAD }
487 #define NFILE asize(fnm)
489 CopyRight(stdout,argv[0]);
490 parse_common_args(&argc,argv,0,NFILE,fnm,
491 0,NULL,asize(desc),desc,0,NULL,&oenv);
493 if ((x11=GetX11(&argc,argv))==NULL) {
494 fprintf(stderr,"Can't connect to X Server.\n"
495 "Check your DISPLAY environment variable\n");
496 exit(1);
498 xhw=GetXHW(x11,opt2fn("-f",NFILE,fnm));
500 XMapWindow(x11->disp,xhw->main.self);
501 XMapSubwindows(x11->disp,xhw->main.self);
502 x11->MainLoop(x11);
503 x11->CleanUp(x11);
505 thanx(stderr);
507 return 0;