#include #include #include #include #include #include #include "display.h" #define P_RADIUS 1.0 struct particle { double x_pos,y_pos; double x_vel,y_vel; double mass; }; typedef struct particle Particle; struct cell { int num_particles; /* number of particles contained here */ int size; /* the array sizes */ Particle* particles; int* flags; /* coordinates of this cell are: lower left = upper right = */ double lx,ly; double ux,uy; /* The following are non null if this cell has a wall. If it does, this pointers point to the vertical or horizontal coor */ double* vwallp; double* hwallp; }; typedef struct cell Cell; struct space { Cell***cells; int ncells_on_margin; /* on a side */ int num_particles; double space_margin_size; /* square world, this is the upper right x and y coor */ double cell_margin_size; double simulation_speed; double inflowRate; double valveSize; }; typedef struct space Space; #define STRING "Particles" #define BORDER 1 #define FONT "fixed" #define ARG_FONT "font" #define ARG_BORDER_COLOR "bordercolor" #define ARG_FOREGROUND "foreground" #define ARG_BACKGROUND "background" #define ARG_BORDER "border" #define ARG_GEOMETRY "geometry" #define DEFAULT_GEOMETRY "" /* * This structure forms the WM_HINTS property of the window, * letting the window manager know how to handle this window. * See Section 9.1 of the Xlib manual. */ XWMHints xwmh = { (InputHint|StateHint), /* flags */ False, /* input */ NormalState, /* initial_state */ 0, /* icon pixmap */ 0, /* icon window */ 0, 0, /* icon location */ 0, /* icon mask */ 0, /* Window group */ }; /* global variables for this program */ Display *dpy; /* X server connection */ Window win; /* Window ID */ GC gc; /* GC to draw with */ struct part_points { int x,y; }; typedef struct part_points PartPoints; int cur_num_points = 0; int part_points_size; #define INCREASEFACTOR 5 #define INCREASEOFFSET 50 PartPoints*oldPoints; void createDisplay(int argc,char *argv[],int wsize,int np) { /* local routine 1 */ unsigned long ftw, fth, pad;/* Font size parameters */ unsigned long fg, bg, bd; /* Pixel values */ unsigned long bw; /* Border width */ char *tempstr; /* Temporary string */ XSizeHints xsh; /* Size hints for window manager */ char *geomSpec; /* Window geometry string */ XSetWindowAttributes xswa; /* Temporary Set Window Attribute struct */ XGCValues gcv; /* Struct for creating GC */ Colormap cmap; /* Color map to use */ XColor color; /* Temporary color */ /* * Open the display using the $DISPLAY environment variable to locate * the X server. See Section 2.1. */ if ((dpy = XOpenDisplay(NULL)) == NULL) { fprintf(stderr, "%s: can't open %s\n", argv[0], XDisplayName(NULL)); exit(1); } /* * Select colors for the border, the window background, and the * foreground. We use the default colormap to allocate the colors in. * See Sections 2.2.1, 5.1.2, & 10.4. */ cmap = DefaultColormap(dpy, DefaultScreen(dpy)); if ((tempstr = XGetDefault(dpy, argv[0], ARG_BORDER_COLOR)) == NULL || XParseColor(dpy, cmap, tempstr, &color) == 0 || XAllocColor(dpy, cmap, &color) == 0) { bd = WhitePixel(dpy, DefaultScreen(dpy)); } else { bd = color.pixel; } if ((tempstr = XGetDefault(dpy, argv[0], ARG_BACKGROUND)) == NULL || XParseColor(dpy, cmap, tempstr, &color) == 0 || XAllocColor(dpy, cmap, &color) == 0) { bg = WhitePixel(dpy, DefaultScreen(dpy)); } else { bg = color.pixel; } if ((tempstr = XGetDefault(dpy, argv[0], ARG_FOREGROUND)) == NULL || XParseColor(dpy, cmap, tempstr, &color) == 0 || XAllocColor(dpy, cmap, &color) == 0) { fg = BlackPixel(dpy, DefaultScreen(dpy)); } else { fg = color.pixel; } /* * Set the border width of the window, and the gap between the text * and the edge of the window, "pad". */ pad = BORDER; if ((tempstr = XGetDefault(dpy, argv[0], ARG_BORDER)) == NULL) bw = 1; else bw = atoi(tempstr); /* * Deal with providing the window with an initial position & size. * Fill out the XSizeHints struct to inform the window manager. See * Sections 9.1.6 & 10.3. */ geomSpec = XGetDefault(dpy, argv[0], ARG_GEOMETRY); if (geomSpec == NULL) { /* * The defaults database doesn't contain a specification of the * initial size & position - fit the window to the text and locate * it in the center of the screen. */ xsh.flags = (PPosition | PSize); xsh.height = ((int)wsize)*2; xsh.width = ((int)wsize)*2; xsh.x = (DisplayWidth(dpy, DefaultScreen(dpy)) - xsh.width) / 2; xsh.y = (DisplayHeight(dpy, DefaultScreen(dpy)) - xsh.height) / 2; } else { int bitmask; bzero((char*)&xsh, sizeof(xsh)); bitmask = XGeometry(dpy, DefaultScreen(dpy), geomSpec, DEFAULT_GEOMETRY, bw, ftw, fth, pad, pad, &(xsh.x), &(xsh.y), &(xsh.width), &(xsh.height)); if (bitmask & (XValue | YValue)) { xsh.flags |= USPosition; } if (bitmask & (WidthValue | HeightValue)) { xsh.flags |= USSize; } } /* * Create the Window with the information in the XSizeHints, the * border width, and the border & background pixels. See Section 3.3. */ win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), xsh.x, xsh.y, xsh.width, xsh.height, bw, bd, bg); /* * Set the standard properties for the window managers. See Section * 9.1. */ XSetStandardProperties(dpy, win, STRING, STRING, None, argv, argc, &xsh); XSetWMHints(dpy, win, &xwmh); /* * Ensure that the window's colormap field points to the default * colormap, so that the window manager knows the correct colormap to * use for the window. See Section 3.2.9. Also, set the window's Bit * Gravity to reduce Expose events. */ xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy)); xswa.bit_gravity = CenterGravity; XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa); /* * Create the GC for writing the text. See Section 5.3. */ gcv.foreground = fg; gcv.background = bg; gc = XCreateGC(dpy, win, (GCForeground | GCBackground), &gcv); /* * Specify the event types we're interested in - only Exposures. See * Sections 8.5 & 8.4.5.1 */ XSelectInput(dpy, win, ExposureMask); /* * Map the window to make it visible. See Section 3.5. */ XMapWindow(dpy, win); XSetFunction(dpy,gc,GXxor); part_points_size = INCREASEFACTOR*np+INCREASEOFFSET; oldPoints = (PartPoints*)malloc(part_points_size*sizeof(PartPoints)); { int i; for (i=0;incells_on_margin;i++) /* x cols, increasing right */ for (j=0;jncells_on_margin;j++) /* y rows, increasing up */ for (k=0;kcells[i][j]->num_particles;k++) { x = ((s->cells[i][j]->particles[k].x_pos-P_RADIUS)/s->space_margin_size) *xwa.width; y = ((s->space_margin_size - s->cells[i][j]->particles[k].y_pos-P_RADIUS)/s->space_margin_size) *xwa.height; /* erase old points and draw new ones */ if (pnum < cur_num_points) { /* erase old point */ XSetFunction(dpy,gc,GXclear); XDrawArc(dpy, win, gc, oldPoints[pnum].x, oldPoints[pnum].y, (int)((P_RADIUS*2.0/s->space_margin_size)*xwa.width), (int)((P_RADIUS*2.0/s->space_margin_size)*xwa.height), 0*64, 360*65); XSetFunction(dpy,gc,GXset); } /* draw new one */ XDrawArc(dpy, win, gc, x, y, (int)((P_RADIUS*2.0/s->space_margin_size)*xwa.width), (int)((P_RADIUS*2.0/s->space_margin_size)*xwa.height), 0*64, 360*65); oldPoints[pnum].x = x; oldPoints[pnum].y = y; pnum++; if (pnum >= part_points_size) { PartPoints*tmp; fprintf(stderr,"Warning: doubling part_points_size from %d\n", part_points_size); tmp = (PartPoints*) malloc(2*part_points_size*sizeof(PartPoints)); bcopy((char*)oldPoints,(char*)tmp,part_points_size*sizeof(PartPoints)); free(oldPoints); oldPoints = tmp; part_points_size *= 2; } } /* clear up any old particles */ new_num_points = pnum; XSetFunction(dpy,gc,GXclear); for (;pnumspace_margin_size)*xwa.width), (int)((P_RADIUS*2.0/s->space_margin_size)*xwa.height), 0*64, 360*65); } cur_num_points = new_num_points; }