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