1 /*
2  * chamber.c -- Larry Medwin -- Dec. 18, 1989
3  *   xgas: Copyright 1990 Larry Medwin: @(#)chamber.c	1.5 2/9/90
4  *   Larry Medwin -- Dec. 18, 1989, April 14, 1991
5  */
6 
7 #include "xgas.h"
8 static void initWall();
9 static void getLabDimensions();
10 
11 /*
12  * Create Graphics Contexts
13  * Initialize client data structure
14  * Initialize allPos array of XRectangles
15  */
labInit(w,data)16 void labInit(w, data)
17     Widget w;
18     LabData *data;
19 {
20     int i, k;
21     Display *dpy = XtDisplay(w);
22     int scr = DefaultScreen(dpy);
23     unsigned long valuemask;
24     XGCValues values;
25 
26     /* Create GC for walls */
27     data->WallGC = XCreateGC( dpy, DefaultRootWindow(dpy), NULL, NULL);
28     XSetForeground( dpy, data->WallGC, data->foreground);
29 
30     /* Create GC for molecules */
31     valuemask = GCFunction | GCPlaneMask | GCForeground | GCBackground;
32     values.function = GXxor;
33     values.plane_mask = values.foreground =
34 	data->background^data->foreground;
35     values.background = data->background;
36     data->MoleculeGC = XCreateGC( dpy, DefaultRootWindow(dpy),
37     	valuemask, &values);
38 
39     /* Initialize the client data structure */
40     data->lab = w;
41     data->nmolecules = 0;
42     data->timestep = 0;
43     data->timer = 0;
44     data->time = 0;
45 
46     for (i=0; i<2; i++) data->chamber[i].temperature = (float)INITTEMP;
47 
48     /* Initialize the allPos array of molecule positions */
49     for( i=0; i<data->maxMolecules; i++) {
50 	for( k=0; k<2; k++) {
51 	    data->allPos[2*i + k].width = (unsigned short) MOLECULE_SIZE;
52 	    data->allPos[2*i + k].height = (unsigned short) MOLECULE_SIZE;
53         }
54     }
55 
56 }
57 
58 /*
59  * LAB RESIZE -- handle resize events.  Makeing this a callback was the
60  *               sole reason for creating the gas widget.
61  */
labResize(w,data,call_data)62 void labResize(w, data, call_data) /* ARGSUSED */
63     Widget w;
64     LabData *data;
65     caddr_t call_data;
66 {
67     Coord p[8];
68 
69     /*
70      * Have to clear out the array of molecules, since some of them
71      * may be outside the walls or in the other box.
72      */
73     data->nmolecules = 0;
74 
75     /* Get dimensions of window in cm */
76     getLabDimensions( w, data);
77 
78     /* Init wall endpoints */
79     p[0].x = 0.0;		p[0].y = 0.0;
80     p[1].x = 0.0;		p[1].y = data->heightMM;
81     p[2].x = data->widthMM/2.0;	p[2].y = 0.0;
82     p[3].x = data->widthMM/2.0;	p[3].y = data->heightMM;
83     p[4].x = data->widthMM;	p[4].y = 0.0;
84     p[5].x = data->widthMM;	p[5].y = data->heightMM;
85     p[6].x = data->widthMM/2.0;	p[6].y = 0.4 * data->heightMM;
86     p[7].x = data->widthMM/2.0;	p[7].y = 0.6 * data->heightMM;
87 
88     initWall( &data->chamber[0].walls[0], p[6], p[7], RIGHT);
89     initWall( &data->chamber[0].walls[1], p[2], p[6], RIGHT);
90     initWall( &data->chamber[0].walls[2], p[0], p[2], TOP);
91     initWall( &data->chamber[0].walls[3], p[0], p[1], LEFT);
92     initWall( &data->chamber[0].walls[4], p[1], p[3], BOTTOM);
93     initWall( &data->chamber[0].walls[5], p[7], p[3], RIGHT);
94 
95     initWall( &data->chamber[1].walls[0], p[6], p[7], LEFT);
96     initWall( &data->chamber[1].walls[1], p[2], p[6], LEFT);
97     initWall( &data->chamber[1].walls[2], p[2], p[4], TOP);
98     initWall( &data->chamber[1].walls[3], p[4], p[5], RIGHT);
99     initWall( &data->chamber[1].walls[4], p[3], p[5], BOTTOM);
100     initWall( &data->chamber[1].walls[5], p[7], p[3], LEFT);
101 }
102 
103 /* INIT WALL */
initWall(wall,end0,end1,type)104 static void initWall( wall, end0, end1, type)
105     Wall *wall;
106     Coord end0, end1;
107     int type;
108 {
109     wall->end[0].x = end0.x;
110     wall->end[0].y = end0.y;
111     wall->end[1].x = end1.x;
112     wall->end[1].y = end1.y;
113     wall->type = type;
114 }
115 
116 /*
117  * WHICH CORNER
118  *    return corner type or 0 if not a corner
119  */
whichCorner(x,y,box,data)120 int whichCorner( x, y, box, data )
121     int x, y, box;
122     LabData *data;
123 {
124 int xmid = data->chamber[0].walls[0].end[0].x;
125 int xend = data->widthMM;
126 int ybot = data->heightMM;
127 
128     /* Check for each box: */
129     if (box == 0) {
130 
131 	/* Check all four corner locations */
132 	if (y == 0 && x == 0) return NW;
133 	if (y == 0 && x == xmid) return NE;
134 	if (y == ybot && x == 0) return SW;
135 	if (y == ybot && x == xmid) return SE;
136 
137 	/* Guess it's not a corner */
138 	return 0;
139     }
140     else { /* box = 1 */
141 	/* Check all four corner locations */
142 	if (y == 0 && x == xmid) return NW;
143 	if (y == 0 && x == xend) return NE;
144 	if (y == ybot && x == xmid) return SW;
145 	if (y == ybot && x == xend) return SE;
146 
147 	/* Not a corner */
148 	return 0;
149     }
150 }
151 
152 /* GET LAB DIMENSIONS */
getLabDimensions(w,data)153 static void getLabDimensions( w, data)
154     Widget w;
155     LabData *data;
156 {
157     Arg wargs[2];
158     int wPix, hPix;
159     float wMM, hMM;
160 
161     /* Get dimensions of lab Widget */
162     XtSetArg( wargs[0], XtNwidth, &data->width);
163     XtSetArg( wargs[1], XtNheight, &data->height);
164     XtGetValues( w, wargs, 2);
165 
166     /* Decrement height and width so that we can draw on these borders */
167     data->width --;
168     data->height --;
169 
170     /* Get scale factor in pixels/cm */
171     wPix = DisplayWidth( XtDisplay(w), DefaultScreen(XtDisplay(w)));
172     wMM = DisplayWidthMM( XtDisplay(w), DefaultScreen(XtDisplay(w)));
173     hPix = DisplayHeight( XtDisplay(w), DefaultScreen(XtDisplay(w)));
174     hMM = DisplayHeightMM( XtDisplay(w), DefaultScreen(XtDisplay(w)));
175 
176     data->scale.x = (int) ( wPix / wMM);
177     data->scale.y = (int) ( hPix / hMM);
178 
179     /* Get dimensions of Chamber in mm */
180     data->widthMM = (float)data->width / (float)data->scale.x;
181     data->heightMM = (float)data->height / (float)data->scale.y;
182 }
183 
184 /*
185  * LAB EXPOSE -- handle expose events
186  *
187  * drawing molecules with XOR
188  *   This event handler must guarantee that molecules are drawn
189  *   exactly once in their current positions, so that they will
190  *   be properly erased by the next XOR.
191  */
labExpose(w,data,event)192 void labExpose( w, data, event)	/* ARGSUSED */
193     Widget w;
194     LabData *data;
195     XEvent *event;
196 {
197     int i, j;
198 
199     /*
200      * Clear the window first
201      *   to make sure that molecules are drawn an even # of times
202      *   on an exposed window
203      */
204     XClearWindow( XtDisplay(w), XtWindow(w));
205 
206     /* Redraw walls */
207     for( i=0; i<2; i++) {
208 
209 	/* Draw walls of Chamber[i] */
210 	for( j=1; j<NWALLS; j++) {
211 	    XDrawLine( XtDisplay(w), XtWindow(w), data->WallGC,
212 	        (int) (data->chamber[i].walls[j].end[0].x * data->scale.x),
213 	        (int) (data->chamber[i].walls[j].end[0].y * data->scale.y),
214 	        (int) (data->chamber[i].walls[j].end[1].x * data->scale.x),
215 	        (int) (data->chamber[i].walls[j].end[1].y * data->scale.y));
216         }
217     }
218 
219     /* Redraw molecules */
220     for( i=0; i<data->nmolecules; i++ ) {
221 	XFillRectangle( XtDisplay(w), XtWindow(w), data->MoleculeGC,
222 	    (int) data->allPos[2*i + data->timestep % 2 ].x,
223 	    (int) data->allPos[2*i + data->timestep % 2 ].y,
224 	    (int) MOLECULE_SIZE, (int) MOLECULE_SIZE);
225     }
226 }
227