3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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
33 * Gyas ROwers Mature At Cryogenic Speed
48 #include "gmx_fatal.h"
50 /* Units are meter and second */
53 int id; /* Identification */
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 */
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 */
73 static const char *Driving[] = { "Start", "Stop" };
74 static const char *Fogs[] = { "Fog", "No Fog" };
76 Quit, StartStop, Fog, NBUT
78 static const char *but_name[NBUT] = { "Quit", "Start", "Fog" };
85 gmx_bool bDriving; /* Are we driving ? */
86 gmx_bool bFog; /* Is it foggy ? */
92 int read_input(t_x11 *x11, const char *fn, t_car **cars, t_input *ir)
96 char buf[100], b2[100];
100 if (fscanf(in, "%d %d %f %f %d",
101 &ir->nlane, &ir->metres, &ir->dt, &ir->min_dist, &ir->sleep) != 5)
103 gmx_fatal(FARGS, "Not enough parameters in %s line 1", fn);
105 if (fscanf(in, "%d", &n) != 1)
107 gmx_fatal(FARGS, "Not enough parameters in %s line 2", fn);
111 for (i = 0; (i < n); i++)
116 if (fscanf(in, "%f %f %f %f %f %s %s", &(c->x), &(c->v), &(c->vwanted),
117 &(c->acc), &(c->brake), buf, b2) != 7)
119 gmx_fatal(FARGS, "Not enough parameters in %s line %d", fn, 3+i);
121 x11->GetNamedColor(x11, buf, &(c->col));
122 x11->GetNamedColor(x11, b2, &(c->roof));
129 static float get_dist(int ncars, t_car cars[], int which, gmx_bool bFog,
130 int dir, int lane, int metres, int *nearest)
145 for (i = 0; (i < ncars); i++)
147 if ((i != which) && (cars[i].oldlane == lane))
149 nd = cars[i].xold-cars[which].xold;
150 if ((nd < 0) && (dir > 0))
154 else if ((nd > 0) && (dir < 0))
159 if (!bFog || (fabs(nd) < 50))
184 void simulate(t_x11 *x11, t_xhighway *xhw,
185 int ncars, t_car cars[], t_input *ir)
187 int i, n_bef, n_bef1, n_beh;
188 float dist, distf, distb;
190 for (i = 0; (i < ncars); i++)
192 cars[i].xold = cars[i].x;
193 cars[i].oldlane = cars[i].lane;
195 for (i = 0; (i < ncars); i++)
197 cars[i].bBrake = FALSE;
198 dist = get_dist(ncars, cars, i, xhw->bFog,
199 1, cars[i].lane, ir->metres, &n_bef);
200 if (dist < ir->min_dist)
202 distf = get_dist(ncars, cars, i, xhw->bFog,
203 1, cars[i].lane+1, ir->metres, &n_bef1);
204 distb = get_dist(ncars, cars, i, xhw->bFog,
205 -1, cars[i].lane+1, ir->metres, &n_beh);
206 if ((cars[i].lane < ir->nlane-1) && (distb >= ir->min_dist) &&
207 (distf >= ir->min_dist))
214 cars[i].v -= cars[i].brake*ir->dt;
221 if ((cars[i].v < cars[n_bef].v) && (dist > ir->min_dist/2))
223 cars[i].v = cars[n_bef].v;
226 cars[i].bBrake = TRUE;
229 else if ((cars[i].lane > 0) && (cars[i].v == cars[i].vwanted))
231 /* Check if I can go right again */
232 dist = get_dist(ncars, cars, i, xhw->bFog,
233 1, cars[i].lane-1, ir->metres, &n_bef);
234 distb = get_dist(ncars, cars, i, xhw->bFog,
235 -1, cars[i].lane-1, ir->metres, &n_beh);
236 if ((dist >= ir->min_dist) && (distb >= ir->min_dist))
242 cars[i].x += cars[i].v*ir->dt;
243 if (cars[i].x > ir->metres)
245 cars[i].x -= ir->metres;
247 if (!cars[i].bBrake && (cars[i].v < cars[i].vwanted))
249 cars[i].v += cars[i].acc*ir->dt;
250 if (cars[i].v > cars[i].vwanted)
252 cars[i].v = cars[i].vwanted;
258 usleep(xhw->ir.sleep);
259 ExposeWin(x11->disp, xhw->win.self);
262 static void Configure(t_xhighway *xhw)
269 h = xhw->main.height;
271 dw = ((float)(w-2))/NBUT-4;
272 for (i = 0; (i < NBUT); i++)
274 t_windata *wd = &(xhw->but[i]);
277 InitWin(wd, 2+i*(dw+4), 2, dw, dh, 1, but_name[i]);
280 self = xhw->win.self;
281 InitWin(&xhw->win, 2, dh+6, w-6, h-dh-10, 1, xhw->main.text);
282 xhw->win.self = self;
285 static void draw_car(Display *disp, Window wd, GC gc,
286 t_car *car, int w0, int h0)
299 XSetForeground(disp, gc, car->col);
300 XFillRectangle(disp, wd, gc, w1, h1, w, h);
303 XSetForeground(disp, gc, car->roof);
304 XFillRectangle(disp, wd, gc, w0-wr/2, h0-hr/2, wr, hr);
309 XSetForeground(disp, gc, YELLOW);
315 XSetForeground(disp, gc, LIGHTRED);
319 for (j = 1; (j < jmax); j++)
323 XDrawLine(disp, wd, gc, w11, h11, w11, h11+hmax);
324 XDrawLine(disp, wd, gc, w11, h11+h-hmax, w11, h11+h);
328 XSetForeground(disp, gc, WHITE);
329 for (j = 1; (j < 3); j++)
333 XDrawLine(disp, wd, gc, w11, h11, w11, h11+3);
334 XDrawLine(disp, wd, gc, w11, h11+h-3, w11, h11+h);
338 static gmx_bool xhwCallBack(struct t_x11 *x11, XEvent *event, Window wd, void *data)
347 xhw = (t_xhighway *)data;
352 nyy = 2*xhw->ir.nlane+1;
355 for (i = 0; (i < nyy); i++)
357 yy[i] = ((float) i*win->height)/(nyy-1);
366 sx = (float)win->width / xhw->ir.metres;
368 XClearWindow(x11->disp, win->self);
369 XSetForeground(x11->disp, x11->gc, WHITE);
371 for (i = 2; (i < nyy-1); i += 2)
373 XDrawLine(x11->disp, win->self, x11->gc, 0, yy[i], win->width-1, yy[i]);
376 for (i = 0; (i < xhw->ncars); i++)
378 t_car *car = &(xhw->cars[i]);
380 int h1 = yy[1+2*(xhw->ir.nlane-1-car->lane)];
382 draw_car(x11->disp, win->self, x11->gc, car, w1, h1);
386 simulate(x11, xhw, xhw->ncars, xhw->cars, &xhw->ir);
391 case ConfigureNotify:
392 if (wd == xhw->main.self)
394 xhw->main.width = event->xconfigure.width;
395 xhw->main.height = event->xconfigure.height;
397 for (i = 0; (i < NBUT); i++)
399 XMoveResizeWindow(x11->disp, xhw->but[i].self,
400 xhw->but[i].x, xhw->but[i].y,
401 xhw->but[i].width, xhw->but[i].height);
403 XMoveResizeWindow(x11->disp, win->self,
404 win->x, win->y, win->width, win->height);
406 else if (wd == win->self)
408 win->width = event->xconfigure.width;
409 win->height = event->xconfigure.height;
420 static gmx_bool butCallBack(struct t_x11 *x11, XEvent *event, Window wd, void *data)
422 XSetWindowAttributes attr;
428 xhw = (t_xhighway *)data;
429 for (i = 0; (i < NBUT); i++)
431 if (xhw->but[i].self == wd)
438 fprintf(stderr, "Incorrect window: %x in butcallback\n", (unsigned)wd);
441 win = &(xhw->but[i]);
446 XClearWindow(x11->disp, win->self);
450 label = Driving[xhw->bDriving];
453 label = Fogs[xhw->bFog];
458 XSetForeground(x11->disp, x11->gc, WHITE);
459 TextInWin(x11, win, label, eXCenter, eYCenter);
462 case ConfigureNotify:
463 win->width = event->xconfigure.width;
464 win->height = event->xconfigure.height;
472 xhw->bDriving = 1-xhw->bDriving;
473 ExposeWin(x11->disp, win->self);
476 ExposeWin(x11->disp, xhw->win.self);
480 xhw->bFog = 1-xhw->bFog;
483 attr.background_pixel = DARKGREY;
487 attr.background_pixel = BLACK;
489 XChangeWindowAttributes(x11->disp, xhw->win.self, CWBackPixel, &attr);
490 /*ExposeWin(x11->disp,win->self);*/
502 t_xhighway *GetXHW(t_x11 *x11, const char *infile)
506 char progname[STRLEN];
509 xhw->ncars = read_input(x11, infile, &(xhw->cars), &xhw->ir);
511 h = xhw->ir.nlane*40;
514 strncpy(progname, Program(), STRLEN-1);
515 InitWin(&xhw->main, 0, 0, w, h+dh+7, 1, progname);
516 xhw->main.self = XCreateSimpleWindow(x11->disp, x11->root,
517 xhw->main.x, xhw->main.y,
518 xhw->main.width, xhw->main.height,
519 xhw->main.bwidth, WHITE, BLACK);
520 x11->RegisterCallback(x11, xhw->main.self, 0, xhwCallBack, xhw);
521 x11->SetInputMask(x11, xhw->main.self, ButtonPressMask | ExposureMask |
522 StructureNotifyMask);
526 for (i = 0; (i < NBUT); i++)
528 t_windata *wd = &(xhw->but[i]);
530 wd->self = XCreateSimpleWindow(x11->disp, xhw->main.self,
532 wd->width, wd->height,
533 wd->bwidth, WHITE, BLACK);
534 x11->RegisterCallback(x11, wd->self, xhw->main.self,
536 x11->SetInputMask(x11, wd->self, ButtonPressMask | ExposureMask |
537 StructureNotifyMask);
540 xhw->win.self = XCreateSimpleWindow(x11->disp, xhw->main.self,
541 xhw->win.x, xhw->win.y,
542 xhw->win.width, xhw->win.height,
543 xhw->win.bwidth, WHITE, BLACK);
544 x11->RegisterCallback(x11, xhw->win.self, 0, xhwCallBack, xhw);
545 x11->SetInputMask(x11, xhw->win.self, ButtonPressMask | ExposureMask |
546 StructureNotifyMask);
551 int main(int argc, char *argv[])
553 const char *desc[] = {
554 "[TT]highway[tt] is the GROMCAS highway simulator. It is an X-windows",
555 "gadget that shows a (periodic) Autobahn with a user defined",
556 "number of cars. Fog can be turned on or off to increase the",
557 "number of crashes. Nice for a background CPU-eater. A sample",
558 "input file is in [TT]$GMXDATA/top/highway.dat[tt]"
564 { efDAT, "-f", "highway", ffREAD }
566 #define NFILE asize(fnm)
568 CopyRight(stderr, argv[0]);
569 parse_common_args(&argc, argv, 0, NFILE, fnm,
570 0, NULL, asize(desc), desc, 0, NULL, &oenv);
572 if ((x11 = GetX11(&argc, argv)) == NULL)
574 fprintf(stderr, "Can't connect to X Server.\n"
575 "Check your DISPLAY environment variable\n");
578 xhw = GetXHW(x11, opt2fn("-f", NFILE, fnm));
580 XMapWindow(x11->disp, xhw->main.self);
581 XMapSubwindows(x11->disp, xhw->main.self);