1 | /* -*- Mode: C; tab-width: 4 -*- */ |
---|
2 | /* crystal --- polygons moving according to plane group rules */ |
---|
3 | |
---|
4 | #if 0 |
---|
5 | static const char sccsid[] = "@(#)crystal.c 4.12 98/09/10 xlockmore"; |
---|
6 | #endif |
---|
7 | |
---|
8 | /*- |
---|
9 | * Copyright (c) 1997 by Jouk Jansen <joukj@crys.chem.uva.nl> |
---|
10 | * |
---|
11 | * Permission to use, copy, modify, and distribute this software and its |
---|
12 | * documentation for any purpose and without fee is hereby granted, |
---|
13 | * provided that the above copyright notice appear in all copies and that |
---|
14 | * both that copyright notice and this permission notice appear in |
---|
15 | * supporting documentation. |
---|
16 | * |
---|
17 | * This file is provided AS IS with no warranties of any kind. The author |
---|
18 | * shall have no liability with respect to the infringement of copyrights, |
---|
19 | * trade secrets or any patents by this file or any part thereof. In no |
---|
20 | * event will the author be liable for any lost revenue or profits or |
---|
21 | * other special, indirect and consequential damages. |
---|
22 | * |
---|
23 | * The author should like to be notified if changes have been made to the |
---|
24 | * routine. Response will only be guaranteed when a VMS version of the |
---|
25 | * program is available. |
---|
26 | * |
---|
27 | * A moving polygon-mode. The polygons obey 2D-planegroup symmetry. |
---|
28 | * |
---|
29 | * The groupings of the cells fall in 3 categories: |
---|
30 | * oblique groups 1 and 2 where the angle gamma ranges from 60 to 120 degrees |
---|
31 | * square groups 3 through 11 where the angle gamma is 90 degrees |
---|
32 | * hexagonal groups 12 through 17 where the angle gamma is 120 degrees |
---|
33 | * |
---|
34 | * Revision History: |
---|
35 | * 03-Dec-98: Random inversion of y-axis included to simulate hexagonal groups |
---|
36 | * with an angle of 60 degrees. |
---|
37 | * 10-Sep-98: new colour scheme |
---|
38 | * 24-Feb-98: added option centre which turns on/off forcing the centre of |
---|
39 | * the screen to be used |
---|
40 | * added option maxsize which forces the dimensions to be chasen |
---|
41 | * in such ua way that the largest possible part of the screen is |
---|
42 | * used |
---|
43 | * When only one unit cell is drawn, it is chosen at random |
---|
44 | * 18-Feb-98: added support for negative numbers with -nx and -ny meaning |
---|
45 | * "random" choice with given maximum |
---|
46 | * added +/-grid option. If -cell is specified this option |
---|
47 | * determines if one or all unit cells are drawn. |
---|
48 | * -batchcount is now a parameter for all the objects on the screen |
---|
49 | * instead of the number of "unique" objects |
---|
50 | * The maximum size of the objects now scales with the part |
---|
51 | * of the screen used. |
---|
52 | * fixed "size" problem. Now very small non-vissable objects |
---|
53 | * are not allowed |
---|
54 | * 13-Feb-98: randomized the unit cell size |
---|
55 | * runtime options -/+cell (turn on/off unit cell drawing) |
---|
56 | * -nx num (number of translational symmetries in x-direction |
---|
57 | * -ny num (idem y-direction but ignored for square and |
---|
58 | * hexagonal space groups |
---|
59 | * i.e. try xlock -mode crystal -nx 3 -ny 2 |
---|
60 | * Fullrandom overrules the -/+cell option. |
---|
61 | * 05-Feb-98: Revision + bug repairs |
---|
62 | * shows unit cell |
---|
63 | * use part of the screen for unit cell |
---|
64 | * in hexagonal and square groups a&b axis forced to be equal |
---|
65 | * cell angle for oblique groups randomly chosen between 60 and 120 |
---|
66 | * bugs solved: planegroups with cell angles <> 90.0 now work properly |
---|
67 | * 19-Sep-97: Added remaining hexagonal groups |
---|
68 | * 12-Jun-97: Created |
---|
69 | */ |
---|
70 | |
---|
71 | #ifdef STANDALONE |
---|
72 | # define PROGCLASS "Crystal" |
---|
73 | # define HACK_INIT init_crystal |
---|
74 | # define HACK_DRAW draw_crystal |
---|
75 | # define crystal_opts xlockmore_opts |
---|
76 | # define DEFAULTS "*delay: 60000 \n" \ |
---|
77 | "*count: -500 \n" \ |
---|
78 | "*cycles: 200 \n" \ |
---|
79 | "*size: -15 \n" \ |
---|
80 | "*ncolors: 100 \n" \ |
---|
81 | "*fullrandom: True \n" \ |
---|
82 | "*verbose: False \n" |
---|
83 | # include "xlockmore.h" /* in xscreensaver distribution */ |
---|
84 | #else /* STANDALONE */ |
---|
85 | # include "xlock.h" /* in xlockmore distribution */ |
---|
86 | # include "color.h" |
---|
87 | #endif /* STANDALONE */ |
---|
88 | |
---|
89 | #define DEF_CELL "True" /* Draw unit cell */ |
---|
90 | #define DEF_GRID "False" /* Draw unit all cell if DEF_CELL is True */ |
---|
91 | #define DEF_NX "-3" /* number of unit cells in x-direction */ |
---|
92 | #define DEF_NX1 1 /* number of unit cells in x-direction */ |
---|
93 | #define DEF_NY "-3" /* number of unit cells in y-direction */ |
---|
94 | #define DEF_NY1 1 /* number of unit cells in y-direction */ |
---|
95 | #define DEF_CENTRE "False" |
---|
96 | #define DEF_MAXSIZE "False" |
---|
97 | #define DEF_CYCLE "True" |
---|
98 | |
---|
99 | #define min(a,b) ((a) <= (b) ? (a) : (b)) |
---|
100 | |
---|
101 | #ifdef STANDALONE |
---|
102 | void release_crystal(ModeInfo * mi); |
---|
103 | #endif |
---|
104 | |
---|
105 | static int nx, ny; |
---|
106 | |
---|
107 | static Bool unit_cell, grid_cell, centre, maxsize, cycle_p; |
---|
108 | |
---|
109 | static XrmOptionDescRec opts[] = |
---|
110 | { |
---|
111 | {"-nx", "crystal.nx", XrmoptionSepArg, (caddr_t) NULL}, |
---|
112 | {"-ny", "crystal.ny", XrmoptionSepArg, (caddr_t) NULL}, |
---|
113 | {"-centre", ".crystal.centre", XrmoptionNoArg, (caddr_t) "on"}, |
---|
114 | {"+centre", ".crystal.centre", XrmoptionNoArg, (caddr_t) "off"}, |
---|
115 | {"-maxsize", ".crystal.maxsize", XrmoptionNoArg, (caddr_t) "on"}, |
---|
116 | {"+maxsize", ".crystal.maxsize", XrmoptionNoArg, (caddr_t) "off"}, |
---|
117 | {"-cell", ".crystal.cell", XrmoptionNoArg, (caddr_t) "on"}, |
---|
118 | {"+cell", ".crystal.cell", XrmoptionNoArg, (caddr_t) "off"}, |
---|
119 | {"-grid", ".crystal.grid", XrmoptionNoArg, (caddr_t) "on"}, |
---|
120 | {"+grid", ".crystal.grid", XrmoptionNoArg, (caddr_t) "off"}, |
---|
121 | {"-shift", ".crystal.shift", XrmoptionNoArg, (caddr_t) "on"}, |
---|
122 | {"+shift", ".crystal.shift", XrmoptionNoArg, (caddr_t) "off"} |
---|
123 | }; |
---|
124 | |
---|
125 | static argtype vars[] = |
---|
126 | { |
---|
127 | {(caddr_t *) & nx, "nx", "nx", DEF_NX, t_Int}, |
---|
128 | {(caddr_t *) & ny, "ny", "ny", DEF_NY, t_Int}, |
---|
129 | {(caddr_t *) & centre, "centre", "Centre", DEF_CENTRE, t_Bool}, |
---|
130 | {(caddr_t *) & maxsize, "maxsize", "Maxsize", DEF_MAXSIZE, t_Bool}, |
---|
131 | {(caddr_t *) & unit_cell, "cell", "Cell", DEF_CELL, t_Bool}, |
---|
132 | {(caddr_t *) & grid_cell, "grid", "Grid", DEF_GRID, t_Bool}, |
---|
133 | {(caddr_t *) & cycle_p, "shift", "Shift", DEF_CYCLE, t_Bool} |
---|
134 | }; |
---|
135 | static OptionStruct desc[] = |
---|
136 | { |
---|
137 | {"-nx num", "Number of unit cells in x-direction"}, |
---|
138 | {"-ny num", "Number of unit cells in y-direction"}, |
---|
139 | {"-/+centre", "turn on/off centering on screen"}, |
---|
140 | {"-/+maxsize", "turn on/off use of maximum part of screen"}, |
---|
141 | {"-/+cell", "turn on/off drawing of unit cell"}, |
---|
142 | {"-/+grid", "turn on/off drawing of grid of unit cells (if -cell is on)"}, |
---|
143 | {"-/+shift", "turn on/off colour cycling"} |
---|
144 | }; |
---|
145 | |
---|
146 | ModeSpecOpt crystal_opts = |
---|
147 | {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; |
---|
148 | |
---|
149 | #ifdef USE_MODULES |
---|
150 | ModStruct crystal_description = |
---|
151 | {"crystal", "init_crystal", "draw_crystal", "release_crystal", |
---|
152 | "refresh_crystal", "init_crystal", NULL, &crystal_opts, |
---|
153 | 60000, -40, 200, -15, 64, 1.0, "", |
---|
154 | "Shows polygons in 2D plane groups", 0, NULL}; |
---|
155 | |
---|
156 | #endif |
---|
157 | |
---|
158 | #define DEF_NUM_ATOM 10 |
---|
159 | |
---|
160 | #define DEF_SIZ_ATOM 10 |
---|
161 | |
---|
162 | #define PI_RAD (M_PI / 180.0) |
---|
163 | |
---|
164 | static Bool centro[17] = |
---|
165 | { |
---|
166 | False, |
---|
167 | True, |
---|
168 | False, |
---|
169 | False, |
---|
170 | False, |
---|
171 | True, |
---|
172 | True, |
---|
173 | True, |
---|
174 | True, |
---|
175 | True, |
---|
176 | True, |
---|
177 | True, |
---|
178 | False, |
---|
179 | False, |
---|
180 | False, |
---|
181 | True, |
---|
182 | True |
---|
183 | }; |
---|
184 | |
---|
185 | static Bool primitive[17] = |
---|
186 | { |
---|
187 | True, |
---|
188 | True, |
---|
189 | True, |
---|
190 | True, |
---|
191 | False, |
---|
192 | True, |
---|
193 | True, |
---|
194 | True, |
---|
195 | False, |
---|
196 | True, |
---|
197 | True, |
---|
198 | True, |
---|
199 | True, |
---|
200 | True, |
---|
201 | True, |
---|
202 | True, |
---|
203 | True |
---|
204 | }; |
---|
205 | |
---|
206 | static short numops[34] = |
---|
207 | { |
---|
208 | 1, 0, |
---|
209 | 1, 0, |
---|
210 | 9, 7, |
---|
211 | 2, 0, |
---|
212 | 9, 7, |
---|
213 | 9, 7, |
---|
214 | 4, 2, |
---|
215 | 5, 3, |
---|
216 | 9, 7, |
---|
217 | 8, 6, |
---|
218 | 10, 6, |
---|
219 | 8, 4, |
---|
220 | 16, 13, |
---|
221 | 19, 13, |
---|
222 | 16, 10, |
---|
223 | 19, 13, |
---|
224 | 19, 13 |
---|
225 | }; |
---|
226 | |
---|
227 | static short operation[114] = |
---|
228 | { |
---|
229 | 1, 0, 0, 1, 0, 0, |
---|
230 | -1, 0, 0, 1, 0, 1, |
---|
231 | -1, 0, 0, 1, 1, 0, |
---|
232 | 1, 0, 0, 1, 0, 0, |
---|
233 | -1, 0, 0, 1, 1, 1, |
---|
234 | 1, 0, 0, 1, 1, 1, |
---|
235 | 0, -1, 1, 0, 0, 0, |
---|
236 | 1, 0, 0, 1, 0, 0, |
---|
237 | -1, 0, 0, 1, 0, 0, |
---|
238 | 0, 1, 1, 0, 0, 0, |
---|
239 | -1, 0, -1, 1, 0, 0, |
---|
240 | 1, -1, 0, -1, 0, 0, |
---|
241 | 0, 1, 1, 0, 0, 0, |
---|
242 | 0, -1, 1, -1, 0, 0, |
---|
243 | -1, 1, -1, 0, 0, 0, |
---|
244 | 1, 0, 0, 1, 0, 0, |
---|
245 | 0, -1, -1, 0, 0, 0, |
---|
246 | -1, 1, 0, 1, 0, 0, |
---|
247 | 1, 0, 1, -1, 0, 0 |
---|
248 | }; |
---|
249 | |
---|
250 | typedef struct { |
---|
251 | unsigned long colour; |
---|
252 | int x0, y0, velocity[2]; |
---|
253 | float angle, velocity_a; |
---|
254 | int num_point, at_type, size_at; |
---|
255 | XPoint xy[5]; |
---|
256 | } crystalatom; |
---|
257 | |
---|
258 | typedef struct { |
---|
259 | Bool painted; |
---|
260 | int win_width, win_height, num_atom; |
---|
261 | int planegroup, a, b, offset_w, offset_h, nx, ny; |
---|
262 | float gamma; |
---|
263 | crystalatom *atom; |
---|
264 | GC gc; |
---|
265 | Bool unit_cell, grid_cell; |
---|
266 | Colormap cmap; |
---|
267 | XColor *colors; |
---|
268 | int ncolors; |
---|
269 | Bool cycle_p, mono_p, no_colors; |
---|
270 | unsigned long blackpixel, whitepixel, fg, bg; |
---|
271 | int direction, invert; |
---|
272 | } crystalstruct; |
---|
273 | |
---|
274 | static crystalstruct *crystals = NULL; |
---|
275 | |
---|
276 | static void |
---|
277 | trans_coor(XPoint * xyp, XPoint * new_xyp, int num_points, |
---|
278 | float gamma) |
---|
279 | { |
---|
280 | int i; |
---|
281 | |
---|
282 | for (i = 0; i <= num_points; i++) { |
---|
283 | new_xyp[i].x = xyp[i].x + |
---|
284 | (int) (xyp[i].y * sin((gamma - 90.0) * PI_RAD)); |
---|
285 | new_xyp[i].y = (int) (xyp[i].y / cos((gamma - 90.0) * PI_RAD)); |
---|
286 | } |
---|
287 | } |
---|
288 | |
---|
289 | static void |
---|
290 | trans_coor_back(XPoint * xyp, XPoint * new_xyp, |
---|
291 | int num_points, float gamma, int offset_w, int offset_h , |
---|
292 | int winheight , int invert ) |
---|
293 | { |
---|
294 | int i; |
---|
295 | |
---|
296 | for (i = 0; i <= num_points; i++) { |
---|
297 | new_xyp[i].y = (int) (xyp[i].y * cos((gamma - 90) * PI_RAD)) + |
---|
298 | offset_h; |
---|
299 | new_xyp[i].x = xyp[i].x - (int) (xyp[i].y * sin((gamma - 90.0) |
---|
300 | * PI_RAD)) + offset_w; |
---|
301 | if ( invert ) new_xyp[i].y = winheight - new_xyp[i].y; |
---|
302 | } |
---|
303 | } |
---|
304 | |
---|
305 | static void |
---|
306 | crystal_setupatom(crystalatom * atom0, float gamma) |
---|
307 | { |
---|
308 | XPoint xy[5]; |
---|
309 | int x0, y0; |
---|
310 | |
---|
311 | y0 = (int) (atom0->y0 * cos((gamma - 90) * PI_RAD)); |
---|
312 | x0 = atom0->x0 - (int) (atom0->y0 * sin((gamma - 90.0) * PI_RAD)); |
---|
313 | switch (atom0->at_type) { |
---|
314 | case 0: /* rectangles */ |
---|
315 | xy[0].x = x0 + (int) (2 * atom0->size_at * |
---|
316 | cos(atom0->angle)) + |
---|
317 | (int) (atom0->size_at * sin(atom0->angle)); |
---|
318 | xy[0].y = y0 + (int) (atom0->size_at * |
---|
319 | cos(atom0->angle)) - |
---|
320 | (int) (2 * atom0->size_at * sin(atom0->angle)); |
---|
321 | xy[1].x = x0 + (int) (2 * atom0->size_at * |
---|
322 | cos(atom0->angle)) - |
---|
323 | (int) (atom0->size_at * sin(atom0->angle)); |
---|
324 | xy[1].y = y0 - (int) (atom0->size_at * |
---|
325 | cos(atom0->angle)) - |
---|
326 | (int) (2 * atom0->size_at * sin(atom0->angle)); |
---|
327 | xy[2].x = x0 - (int) (2 * atom0->size_at * |
---|
328 | cos(atom0->angle)) - |
---|
329 | (int) (atom0->size_at * sin(atom0->angle)); |
---|
330 | xy[2].y = y0 - (int) (atom0->size_at * |
---|
331 | cos(atom0->angle)) + |
---|
332 | (int) (2 * atom0->size_at * sin(atom0->angle)); |
---|
333 | xy[3].x = x0 - (int) (2 * atom0->size_at * |
---|
334 | cos(atom0->angle)) + |
---|
335 | (int) (atom0->size_at * sin(atom0->angle)); |
---|
336 | xy[3].y = y0 + (int) (atom0->size_at * |
---|
337 | cos(atom0->angle)) + |
---|
338 | (int) (2 * atom0->size_at * |
---|
339 | sin(atom0->angle)); |
---|
340 | xy[4].x = xy[0].x; |
---|
341 | xy[4].y = xy[0].y; |
---|
342 | trans_coor(xy, atom0->xy, 4, gamma); |
---|
343 | return; |
---|
344 | case 1: /* squares */ |
---|
345 | xy[0].x = x0 + (int) (1.5 * atom0->size_at * |
---|
346 | cos(atom0->angle)) + |
---|
347 | (int) (1.5 * atom0->size_at * |
---|
348 | sin(atom0->angle)); |
---|
349 | xy[0].y = y0 + (int) (1.5 * atom0->size_at * |
---|
350 | cos(atom0->angle)) - |
---|
351 | (int) (1.5 * atom0->size_at * |
---|
352 | sin(atom0->angle)); |
---|
353 | xy[1].x = x0 + (int) (1.5 * atom0->size_at * |
---|
354 | cos(atom0->angle)) - |
---|
355 | (int) (1.5 * atom0->size_at * |
---|
356 | sin(atom0->angle)); |
---|
357 | xy[1].y = y0 - (int) (1.5 * atom0->size_at * |
---|
358 | cos(atom0->angle)) - |
---|
359 | (int) (1.5 * atom0->size_at * |
---|
360 | sin(atom0->angle)); |
---|
361 | xy[2].x = x0 - (int) (1.5 * atom0->size_at * |
---|
362 | cos(atom0->angle)) - |
---|
363 | (int) (1.5 * atom0->size_at * |
---|
364 | sin(atom0->angle)); |
---|
365 | xy[2].y = y0 - (int) (1.5 * atom0->size_at * |
---|
366 | cos(atom0->angle)) + |
---|
367 | (int) (1.5 * atom0->size_at * |
---|
368 | sin(atom0->angle)); |
---|
369 | xy[3].x = x0 - (int) (1.5 * atom0->size_at * |
---|
370 | cos(atom0->angle)) + |
---|
371 | (int) (1.5 * atom0->size_at * |
---|
372 | sin(atom0->angle)); |
---|
373 | xy[3].y = y0 + (int) (1.5 * atom0->size_at * |
---|
374 | cos(atom0->angle)) + |
---|
375 | (int) (1.5 * atom0->size_at * |
---|
376 | sin(atom0->angle)); |
---|
377 | xy[4].x = xy[0].x; |
---|
378 | xy[4].y = xy[0].y; |
---|
379 | trans_coor(xy, atom0->xy, 4, gamma); |
---|
380 | return; |
---|
381 | case 2: /* triangles */ |
---|
382 | xy[0].x = x0 + (int) (1.5 * atom0->size_at * |
---|
383 | sin(atom0->angle)); |
---|
384 | xy[0].y = y0 + (int) (1.5 * atom0->size_at * |
---|
385 | cos(atom0->angle)); |
---|
386 | xy[1].x = x0 + (int) (1.5 * atom0->size_at * |
---|
387 | cos(atom0->angle)) - |
---|
388 | (int) (1.5 * atom0->size_at * |
---|
389 | sin(atom0->angle)); |
---|
390 | xy[1].y = y0 - (int) (1.5 * atom0->size_at * |
---|
391 | cos(atom0->angle)) - |
---|
392 | (int) (1.5 * atom0->size_at * |
---|
393 | sin(atom0->angle)); |
---|
394 | xy[2].x = x0 - (int) (1.5 * atom0->size_at * |
---|
395 | cos(atom0->angle)) - |
---|
396 | (int) (1.5 * atom0->size_at * |
---|
397 | sin(atom0->angle)); |
---|
398 | xy[2].y = y0 - (int) (1.5 * atom0->size_at * |
---|
399 | cos(atom0->angle)) + |
---|
400 | (int) (1.5 * atom0->size_at * |
---|
401 | sin(atom0->angle)); |
---|
402 | xy[3].x = xy[0].x; |
---|
403 | xy[3].y = xy[0].y; |
---|
404 | trans_coor(xy, atom0->xy, 3, gamma); |
---|
405 | return; |
---|
406 | } |
---|
407 | } |
---|
408 | |
---|
409 | static void |
---|
410 | crystal_drawatom(ModeInfo * mi, crystalatom * atom0) |
---|
411 | { |
---|
412 | crystalstruct *cryst; |
---|
413 | Display *display = MI_DISPLAY(mi); |
---|
414 | Window window = MI_WINDOW(mi); |
---|
415 | int j, k, l, m; |
---|
416 | |
---|
417 | cryst = &crystals[MI_SCREEN(mi)]; |
---|
418 | for (j = numops[2 * cryst->planegroup + 1]; |
---|
419 | j < numops[2 * cryst->planegroup]; j++) { |
---|
420 | XPoint xy[5], new_xy[5]; |
---|
421 | XPoint xy_1[5]; |
---|
422 | int xtrans, ytrans; |
---|
423 | |
---|
424 | xtrans = operation[j * 6] * atom0->x0 + operation[j * 6 + 1] * |
---|
425 | atom0->y0 + (int) (operation[j * 6 + 4] * cryst->a / |
---|
426 | 2.0); |
---|
427 | ytrans = operation[j * 6 + 2] * atom0->x0 + operation[j * 6 + |
---|
428 | 3] * atom0->y0 + (int) (operation[j * 6 + 5] * |
---|
429 | cryst->b / 2.0); |
---|
430 | if (xtrans < 0) { |
---|
431 | if (xtrans < -cryst->a) |
---|
432 | xtrans = 2 * cryst->a; |
---|
433 | else |
---|
434 | xtrans = cryst->a; |
---|
435 | } else if (xtrans >= cryst->a) |
---|
436 | xtrans = -cryst->a; |
---|
437 | else |
---|
438 | xtrans = 0; |
---|
439 | if (ytrans < 0) |
---|
440 | ytrans = cryst->b; |
---|
441 | else if (ytrans >= cryst->b) |
---|
442 | ytrans = -cryst->b; |
---|
443 | else |
---|
444 | ytrans = 0; |
---|
445 | for (k = 0; k < atom0->num_point; k++) { |
---|
446 | xy[k].x = operation[j * 6] * atom0->xy[k].x + |
---|
447 | operation[j * 6 + 1] * |
---|
448 | atom0->xy[k].y + (int) (operation[j * 6 + 4] * |
---|
449 | cryst->a / 2.0) + |
---|
450 | xtrans; |
---|
451 | xy[k].y = operation[j * 6 + 2] * atom0->xy[k].x + |
---|
452 | operation[j * 6 + 3] * |
---|
453 | atom0->xy[k].y + (int) (operation[j * 6 + 5] * |
---|
454 | cryst->b / 2.0) + |
---|
455 | ytrans; |
---|
456 | } |
---|
457 | xy[atom0->num_point].x = xy[0].x; |
---|
458 | xy[atom0->num_point].y = xy[0].y; |
---|
459 | for (l = 0; l < cryst->nx; l++) { |
---|
460 | for (m = 0; m < cryst->ny; m++) { |
---|
461 | |
---|
462 | for (k = 0; k <= atom0->num_point; k++) { |
---|
463 | xy_1[k].x = xy[k].x + l * cryst->a; |
---|
464 | xy_1[k].y = xy[k].y + m * cryst->b; |
---|
465 | } |
---|
466 | trans_coor_back(xy_1, new_xy, atom0->num_point, |
---|
467 | cryst->gamma, cryst->offset_w, |
---|
468 | cryst->offset_h , |
---|
469 | cryst->win_height, |
---|
470 | cryst->invert); |
---|
471 | XFillPolygon(display, window, cryst->gc, new_xy, |
---|
472 | atom0->num_point, Convex, CoordModeOrigin); |
---|
473 | } |
---|
474 | } |
---|
475 | if (centro[cryst->planegroup] == True) { |
---|
476 | for (k = 0; k <= atom0->num_point; k++) { |
---|
477 | xy[k].x = cryst->a - xy[k].x; |
---|
478 | xy[k].y = cryst->b - xy[k].y; |
---|
479 | } |
---|
480 | for (l = 0; l < cryst->nx; l++) { |
---|
481 | for (m = 0; m < cryst->ny; m++) { |
---|
482 | |
---|
483 | for (k = 0; k <= atom0->num_point; k++) { |
---|
484 | xy_1[k].x = xy[k].x + l * cryst->a; |
---|
485 | xy_1[k].y = xy[k].y + m * cryst->b; |
---|
486 | } |
---|
487 | trans_coor_back(xy_1, new_xy, atom0->num_point, |
---|
488 | cryst->gamma, |
---|
489 | cryst->offset_w, |
---|
490 | cryst->offset_h , |
---|
491 | cryst->win_height , |
---|
492 | cryst->invert); |
---|
493 | XFillPolygon(display, window, cryst->gc, |
---|
494 | new_xy, |
---|
495 | atom0->num_point, Convex, |
---|
496 | CoordModeOrigin); |
---|
497 | } |
---|
498 | } |
---|
499 | } |
---|
500 | if (primitive[cryst->planegroup] == False) { |
---|
501 | if (xy[atom0->num_point].x >= (int) (cryst->a / 2.0)) |
---|
502 | xtrans = (int) (-cryst->a / 2.0); |
---|
503 | else |
---|
504 | xtrans = (int) (cryst->a / 2.0); |
---|
505 | if (xy[atom0->num_point].y >= (int) (cryst->b / 2.0)) |
---|
506 | ytrans = (int) (-cryst->b / 2.0); |
---|
507 | else |
---|
508 | ytrans = (int) (cryst->b / 2.0); |
---|
509 | for (k = 0; k <= atom0->num_point; k++) { |
---|
510 | xy[k].x = xy[k].x + xtrans; |
---|
511 | xy[k].y = xy[k].y + ytrans; |
---|
512 | } |
---|
513 | for (l = 0; l < cryst->nx; l++) { |
---|
514 | for (m = 0; m < cryst->ny; m++) { |
---|
515 | |
---|
516 | for (k = 0; k <= atom0->num_point; k++) { |
---|
517 | xy_1[k].x = xy[k].x + l * cryst->a; |
---|
518 | xy_1[k].y = xy[k].y + m * cryst->b; |
---|
519 | } |
---|
520 | trans_coor_back(xy_1, new_xy, atom0->num_point, |
---|
521 | cryst->gamma, |
---|
522 | cryst->offset_w, |
---|
523 | cryst->offset_h , |
---|
524 | cryst->win_height, |
---|
525 | cryst->invert); |
---|
526 | XFillPolygon(display, window, cryst->gc, |
---|
527 | new_xy, |
---|
528 | atom0->num_point, Convex, |
---|
529 | CoordModeOrigin); |
---|
530 | } |
---|
531 | } |
---|
532 | if (centro[cryst->planegroup] == True) { |
---|
533 | XPoint xy1[5]; |
---|
534 | |
---|
535 | for (k = 0; k <= atom0->num_point; k++) { |
---|
536 | xy1[k].x = cryst->a - xy[k].x; |
---|
537 | xy1[k].y = cryst->b - xy[k].y; |
---|
538 | } |
---|
539 | for (l = 0; l < cryst->nx; l++) { |
---|
540 | for (m = 0; m < cryst->ny; m++) { |
---|
541 | |
---|
542 | for (k = 0; k <= atom0->num_point; k++) { |
---|
543 | xy_1[k].x = xy1[k].x + l * cryst->a; |
---|
544 | xy_1[k].y = xy1[k].y + m * cryst->b; |
---|
545 | } |
---|
546 | trans_coor_back(xy_1, new_xy, atom0->num_point, |
---|
547 | cryst->gamma, |
---|
548 | cryst->offset_w, |
---|
549 | cryst->offset_h , |
---|
550 | cryst->win_height, |
---|
551 | cryst->invert); |
---|
552 | XFillPolygon(display, window, |
---|
553 | cryst->gc, |
---|
554 | new_xy, atom0->num_point, |
---|
555 | Convex, CoordModeOrigin); |
---|
556 | } |
---|
557 | } |
---|
558 | } |
---|
559 | } |
---|
560 | } |
---|
561 | } |
---|
562 | |
---|
563 | void |
---|
564 | draw_crystal(ModeInfo * mi) |
---|
565 | { |
---|
566 | Display *display = MI_DISPLAY(mi); |
---|
567 | crystalstruct *cryst = &crystals[MI_SCREEN(mi)]; |
---|
568 | int i; |
---|
569 | |
---|
570 | if (cryst->no_colors) { |
---|
571 | release_crystal(mi); |
---|
572 | init_crystal(mi); |
---|
573 | return; |
---|
574 | } |
---|
575 | cryst->painted = True; |
---|
576 | MI_IS_DRAWN(mi) = True; |
---|
577 | XSetFunction(display, cryst->gc, GXxor); |
---|
578 | |
---|
579 | /* Rotate colours */ |
---|
580 | if (cryst->cycle_p) { |
---|
581 | rotate_colors(display, cryst->cmap, cryst->colors, cryst->ncolors, |
---|
582 | cryst->direction); |
---|
583 | if (!(LRAND() % 1000)) |
---|
584 | cryst->direction = -cryst->direction; |
---|
585 | } |
---|
586 | for (i = 0; i < cryst->num_atom; i++) { |
---|
587 | crystalatom *atom0; |
---|
588 | |
---|
589 | atom0 = &cryst->atom[i]; |
---|
590 | |
---|
591 | if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { |
---|
592 | XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel); |
---|
593 | } else { |
---|
594 | XSetForeground(display, cryst->gc, atom0->colour); |
---|
595 | } |
---|
596 | crystal_drawatom(mi, atom0); |
---|
597 | atom0->velocity[0] += NRAND(3) - 1; |
---|
598 | atom0->velocity[0] = MAX(-20, MIN(20, atom0->velocity[0])); |
---|
599 | atom0->velocity[1] += NRAND(3) - 1; |
---|
600 | atom0->velocity[1] = MAX(-20, MIN(20, atom0->velocity[1])); |
---|
601 | atom0->x0 += atom0->velocity[0]; |
---|
602 | /*if (cryst->gamma == 90.0) { */ |
---|
603 | if (atom0->x0 < 0) |
---|
604 | atom0->x0 += cryst->a; |
---|
605 | else if (atom0->x0 >= cryst->a) |
---|
606 | atom0->x0 -= cryst->a; |
---|
607 | atom0->y0 += atom0->velocity[1]; |
---|
608 | if (atom0->y0 < 0) |
---|
609 | atom0->y0 += cryst->b; |
---|
610 | else if (atom0->y0 >= cryst->b) |
---|
611 | atom0->y0 -= cryst->b; |
---|
612 | /*} */ |
---|
613 | atom0->velocity_a += ((float) NRAND(1001) - 500.0) / 2000.0; |
---|
614 | atom0->angle += atom0->velocity_a; |
---|
615 | crystal_setupatom(atom0, cryst->gamma); |
---|
616 | crystal_drawatom(mi, atom0); |
---|
617 | } |
---|
618 | XSetFunction(display, cryst->gc, GXcopy); |
---|
619 | } |
---|
620 | |
---|
621 | void |
---|
622 | refresh_crystal(ModeInfo * mi) |
---|
623 | { |
---|
624 | Display *display = MI_DISPLAY(mi); |
---|
625 | Window window = MI_WINDOW(mi); |
---|
626 | crystalstruct *cryst = &crystals[MI_SCREEN(mi)]; |
---|
627 | int i; |
---|
628 | |
---|
629 | if (!cryst->painted) |
---|
630 | return; |
---|
631 | MI_CLEARWINDOW(mi); |
---|
632 | XSetFunction(display, cryst->gc, GXxor); |
---|
633 | |
---|
634 | if (cryst->unit_cell) { |
---|
635 | int y_coor1 , y_coor2; |
---|
636 | |
---|
637 | if (MI_NPIXELS(mi) > 2) |
---|
638 | XSetForeground(display, cryst->gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)))); |
---|
639 | else |
---|
640 | XSetForeground(display, cryst->gc, MI_WHITE_PIXEL(mi)); |
---|
641 | if (cryst->grid_cell) { |
---|
642 | int inx, iny; |
---|
643 | |
---|
644 | if ( cryst->invert ) |
---|
645 | y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h; |
---|
646 | else |
---|
647 | y_coor1 = y_coor2 = cryst->offset_h; |
---|
648 | XDrawLine(display, window, cryst->gc, cryst->offset_w, |
---|
649 | y_coor1, cryst->offset_w + cryst->nx * cryst->a, |
---|
650 | y_coor2); |
---|
651 | if ( cryst->invert ) |
---|
652 | { |
---|
653 | y_coor1 = cryst->win_height - cryst->offset_h; |
---|
654 | y_coor2 = cryst->win_height - (int) (cryst->ny * |
---|
655 | cryst->b * |
---|
656 | cos((cryst->gamma - 90) * PI_RAD)) - |
---|
657 | cryst->offset_h; |
---|
658 | } |
---|
659 | else |
---|
660 | { |
---|
661 | y_coor1 = cryst->offset_h; |
---|
662 | y_coor2 = (int) (cryst->ny * cryst->b * |
---|
663 | cos((cryst->gamma - 90) * PI_RAD)) + |
---|
664 | cryst->offset_h; |
---|
665 | } |
---|
666 | XDrawLine(display, window, cryst->gc, cryst->offset_w, |
---|
667 | y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b * |
---|
668 | sin((cryst->gamma - 90) * PI_RAD)), |
---|
669 | y_coor2); |
---|
670 | inx = cryst->nx; |
---|
671 | for (iny = 1; iny <= cryst->ny; iny++) { |
---|
672 | if ( cryst->invert ) |
---|
673 | { |
---|
674 | y_coor1 = cryst->win_height - |
---|
675 | (int) (iny * cryst->b * cos((cryst->gamma - 90) * |
---|
676 | PI_RAD)) - cryst->offset_h; |
---|
677 | y_coor2 = cryst->win_height - |
---|
678 | (int) (iny * cryst->b * cos((cryst->gamma - 90) * |
---|
679 | PI_RAD)) - |
---|
680 | cryst->offset_h; |
---|
681 | } |
---|
682 | else |
---|
683 | { |
---|
684 | y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * |
---|
685 | PI_RAD)) + cryst->offset_h; |
---|
686 | y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) + |
---|
687 | cryst->offset_h; |
---|
688 | } |
---|
689 | XDrawLine(display, window, cryst->gc, |
---|
690 | (int) (cryst->offset_w + |
---|
691 | inx * cryst->a - (int) (iny * cryst->b * |
---|
692 | sin((cryst->gamma - 90) * PI_RAD))), |
---|
693 | y_coor1, |
---|
694 | (int) (cryst->offset_w - iny * cryst->b * |
---|
695 | sin((cryst->gamma - 90) * PI_RAD)), |
---|
696 | y_coor2); |
---|
697 | } |
---|
698 | iny = cryst->ny; |
---|
699 | for (inx = 1; inx <= cryst->nx; inx++) { |
---|
700 | if ( cryst->invert ) |
---|
701 | { |
---|
702 | y_coor1 =cryst->win_height - |
---|
703 | (int) (iny * cryst->b * |
---|
704 | cos((cryst->gamma - 90) * |
---|
705 | PI_RAD)) - cryst->offset_h; |
---|
706 | y_coor2 =cryst->win_height - cryst->offset_h; |
---|
707 | } |
---|
708 | else |
---|
709 | { |
---|
710 | y_coor1 =(int) (iny * cryst->b * |
---|
711 | cos((cryst->gamma - 90) * |
---|
712 | PI_RAD)) + cryst->offset_h; |
---|
713 | y_coor2 =cryst->offset_h; |
---|
714 | } |
---|
715 | XDrawLine(display, window, cryst->gc, |
---|
716 | (int) (cryst->offset_w + |
---|
717 | inx * cryst->a - (int) (iny * cryst->b * |
---|
718 | sin((cryst->gamma - 90) * PI_RAD))), |
---|
719 | y_coor1, |
---|
720 | cryst->offset_w + inx * cryst->a, |
---|
721 | y_coor2); |
---|
722 | } |
---|
723 | } else { |
---|
724 | int inx, iny; |
---|
725 | |
---|
726 | inx = NRAND(cryst->nx); |
---|
727 | iny = NRAND(cryst->ny); |
---|
728 | if ( cryst->invert ) |
---|
729 | { |
---|
730 | y_coor1 =cryst->win_height - |
---|
731 | (int) (iny * cryst->b * |
---|
732 | cos((cryst->gamma - 90) * |
---|
733 | PI_RAD)) - |
---|
734 | cryst->offset_h; |
---|
735 | y_coor2 =cryst->win_height - |
---|
736 | (int) ( ( iny + 1 ) * cryst->b * |
---|
737 | cos((cryst->gamma - 90) * |
---|
738 | PI_RAD)) - |
---|
739 | cryst->offset_h; |
---|
740 | } |
---|
741 | else |
---|
742 | { |
---|
743 | y_coor1 =(int) (iny * cryst->b * |
---|
744 | cos((cryst->gamma - 90) * |
---|
745 | PI_RAD)) + |
---|
746 | cryst->offset_h; |
---|
747 | y_coor2 =(int) (( iny + 1 ) * cryst->b * |
---|
748 | cos((cryst->gamma - 90) * |
---|
749 | PI_RAD)) + |
---|
750 | cryst->offset_h; |
---|
751 | } |
---|
752 | XDrawLine(display, window, cryst->gc, |
---|
753 | cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
754 | y_coor1, |
---|
755 | cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
756 | y_coor1); |
---|
757 | XDrawLine(display, window, cryst->gc, |
---|
758 | cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
759 | y_coor1, |
---|
760 | cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
761 | y_coor2); |
---|
762 | XDrawLine(display, window, cryst->gc, |
---|
763 | cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
764 | y_coor1, |
---|
765 | cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
766 | y_coor2); |
---|
767 | XDrawLine(display, window, cryst->gc, |
---|
768 | cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
769 | y_coor2, |
---|
770 | cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
771 | y_coor2); |
---|
772 | } |
---|
773 | } |
---|
774 | for (i = 0; i < cryst->num_atom; i++) { |
---|
775 | crystalatom *atom0; |
---|
776 | |
---|
777 | atom0 = &cryst->atom[i]; |
---|
778 | if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { |
---|
779 | XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel); |
---|
780 | } else { |
---|
781 | XSetForeground(display, cryst->gc, atom0->colour); |
---|
782 | } |
---|
783 | crystal_drawatom(mi, atom0); |
---|
784 | } |
---|
785 | XSetFunction(display, cryst->gc, GXcopy); |
---|
786 | } |
---|
787 | |
---|
788 | void |
---|
789 | release_crystal(ModeInfo * mi) |
---|
790 | { |
---|
791 | Display *display = MI_DISPLAY(mi); |
---|
792 | |
---|
793 | if (crystals != NULL) { |
---|
794 | int screen; |
---|
795 | |
---|
796 | for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { |
---|
797 | crystalstruct *cryst = &crystals[screen]; |
---|
798 | |
---|
799 | if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { |
---|
800 | MI_WHITE_PIXEL(mi) = cryst->whitepixel; |
---|
801 | MI_BLACK_PIXEL(mi) = cryst->blackpixel; |
---|
802 | #ifndef STANDALONE |
---|
803 | MI_FG_PIXEL(mi) = cryst->fg; |
---|
804 | MI_BG_PIXEL(mi) = cryst->bg; |
---|
805 | #endif |
---|
806 | if (cryst->colors && cryst->ncolors && !cryst->no_colors) |
---|
807 | free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors); |
---|
808 | if (cryst->colors) |
---|
809 | (void) free((void *) cryst->colors); |
---|
810 | #if 0 /* #### wrong! -jwz */ |
---|
811 | XFreeColormap(display, cryst->cmap); |
---|
812 | #endif |
---|
813 | } |
---|
814 | if (cryst->gc != NULL) |
---|
815 | XFreeGC(display, cryst->gc); |
---|
816 | if (cryst->atom != NULL) |
---|
817 | (void) free((void *) cryst->atom); |
---|
818 | } |
---|
819 | (void) free((void *) crystals); |
---|
820 | crystals = NULL; |
---|
821 | } |
---|
822 | } |
---|
823 | |
---|
824 | void |
---|
825 | init_crystal(ModeInfo * mi) |
---|
826 | { |
---|
827 | Display *display = MI_DISPLAY(mi); |
---|
828 | Window window = MI_WINDOW(mi); |
---|
829 | crystalstruct *cryst; |
---|
830 | int i, max_atoms, size_atom, neqv; |
---|
831 | int cell_min; |
---|
832 | |
---|
833 | #define MIN_CELL 200 |
---|
834 | |
---|
835 | /* initialize */ |
---|
836 | if (crystals == NULL) { |
---|
837 | if ((crystals = (crystalstruct *) calloc(MI_NUM_SCREENS(mi), |
---|
838 | sizeof (crystalstruct))) == NULL) |
---|
839 | return; |
---|
840 | } |
---|
841 | cryst = &crystals[MI_SCREEN(mi)]; |
---|
842 | |
---|
843 | if (!cryst->gc) { |
---|
844 | if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { |
---|
845 | XColor color; |
---|
846 | |
---|
847 | #ifndef STANDALONE |
---|
848 | extern char *background; |
---|
849 | extern char *foreground; |
---|
850 | |
---|
851 | cryst->fg = MI_FG_PIXEL(mi); |
---|
852 | cryst->bg = MI_BG_PIXEL(mi); |
---|
853 | #endif |
---|
854 | cryst->blackpixel = MI_BLACK_PIXEL(mi); |
---|
855 | cryst->whitepixel = MI_WHITE_PIXEL(mi); |
---|
856 | #if 0 /* #### wrong! -jwz */ |
---|
857 | cryst->cmap = XCreateColormap(display, window, |
---|
858 | MI_VISUAL(mi), AllocNone); |
---|
859 | XSetWindowColormap(display, window, cryst->cmap); |
---|
860 | #else |
---|
861 | cryst->cmap = mi->xgwa.colormap; |
---|
862 | #endif |
---|
863 | (void) XParseColor(display, cryst->cmap, "black", &color); |
---|
864 | (void) XAllocColor(display, cryst->cmap, &color); |
---|
865 | MI_BLACK_PIXEL(mi) = color.pixel; |
---|
866 | (void) XParseColor(display, cryst->cmap, "white", &color); |
---|
867 | (void) XAllocColor(display, cryst->cmap, &color); |
---|
868 | MI_WHITE_PIXEL(mi) = color.pixel; |
---|
869 | #ifndef STANDALONE |
---|
870 | (void) XParseColor(display, cryst->cmap, background, &color); |
---|
871 | (void) XAllocColor(display, cryst->cmap, &color); |
---|
872 | MI_BG_PIXEL(mi) = color.pixel; |
---|
873 | (void) XParseColor(display, cryst->cmap, foreground, &color); |
---|
874 | (void) XAllocColor(display, cryst->cmap, &color); |
---|
875 | MI_FG_PIXEL(mi) = color.pixel; |
---|
876 | #endif |
---|
877 | cryst->colors = 0; |
---|
878 | cryst->ncolors = 0; |
---|
879 | } |
---|
880 | if ((cryst->gc = XCreateGC(display, MI_WINDOW(mi), |
---|
881 | (unsigned long) 0, (XGCValues *) NULL)) == None) |
---|
882 | return; |
---|
883 | } |
---|
884 | /* Clear Display */ |
---|
885 | MI_CLEARWINDOW(mi); |
---|
886 | cryst->painted = False; |
---|
887 | XSetFunction(display, cryst->gc, GXxor); |
---|
888 | |
---|
889 | |
---|
890 | /*Set up crystal data */ |
---|
891 | cryst->direction = (LRAND() & 1) ? 1 : -1; |
---|
892 | if (MI_IS_FULLRANDOM(mi)) { |
---|
893 | if (LRAND() & 1) |
---|
894 | cryst->unit_cell = True; |
---|
895 | else |
---|
896 | cryst->unit_cell = False; |
---|
897 | } else |
---|
898 | cryst->unit_cell = unit_cell; |
---|
899 | if (cryst->unit_cell) { |
---|
900 | if (MI_IS_FULLRANDOM(mi)) { |
---|
901 | if (LRAND() & 1) |
---|
902 | cryst->grid_cell = True; |
---|
903 | else |
---|
904 | cryst->grid_cell = False; |
---|
905 | } else |
---|
906 | cryst->grid_cell = grid_cell; |
---|
907 | } |
---|
908 | cryst->win_width = MI_WIDTH(mi); |
---|
909 | cryst->win_height = MI_HEIGHT(mi); |
---|
910 | cell_min = min(cryst->win_width / 2 + 1, MIN_CELL); |
---|
911 | cell_min = min(cell_min, cryst->win_height / 2 + 1); |
---|
912 | cryst->planegroup = NRAND(17); |
---|
913 | cryst->invert = NRAND(2); |
---|
914 | if (MI_IS_VERBOSE(mi)) |
---|
915 | (void) fprintf(stdout, "Selected plane group no %d\n", |
---|
916 | cryst->planegroup + 1); |
---|
917 | if (cryst->planegroup > 11) |
---|
918 | cryst->gamma = 120.0; |
---|
919 | else if (cryst->planegroup < 2) |
---|
920 | cryst->gamma = 60.0 + NRAND(60); |
---|
921 | else |
---|
922 | cryst->gamma = 90.0; |
---|
923 | neqv = numops[2 * cryst->planegroup] - numops[2 * cryst->planegroup + 1]; |
---|
924 | if (centro[cryst->planegroup] == True) |
---|
925 | neqv = 2 * neqv; |
---|
926 | if (primitive[cryst->planegroup] == False) |
---|
927 | neqv = 2 * neqv; |
---|
928 | |
---|
929 | |
---|
930 | if (nx > 0) |
---|
931 | cryst->nx = nx; |
---|
932 | else if (nx < 0) |
---|
933 | cryst->nx = NRAND(-nx) + 1; |
---|
934 | else |
---|
935 | cryst->nx = DEF_NX1; |
---|
936 | if (cryst->planegroup > 8) |
---|
937 | cryst->ny = cryst->nx; |
---|
938 | else if (ny > 0) |
---|
939 | cryst->ny = ny; |
---|
940 | else if (ny < 0) |
---|
941 | cryst->ny = NRAND(-ny) + 1; |
---|
942 | else |
---|
943 | cryst->ny = DEF_NY1; |
---|
944 | neqv = neqv * cryst->nx * cryst->ny; |
---|
945 | |
---|
946 | cryst->num_atom = MI_COUNT(mi); |
---|
947 | max_atoms = MI_COUNT(mi); |
---|
948 | if (cryst->num_atom == 0) { |
---|
949 | cryst->num_atom = DEF_NUM_ATOM; |
---|
950 | max_atoms = DEF_NUM_ATOM; |
---|
951 | } else if (cryst->num_atom < 0) { |
---|
952 | max_atoms = -cryst->num_atom; |
---|
953 | cryst->num_atom = NRAND(-cryst->num_atom) + 1; |
---|
954 | } |
---|
955 | if (neqv > 1) |
---|
956 | cryst->num_atom = cryst->num_atom / neqv + 1; |
---|
957 | |
---|
958 | if (cryst->atom == NULL) |
---|
959 | cryst->atom = (crystalatom *) calloc(max_atoms, sizeof ( |
---|
960 | crystalatom)); |
---|
961 | |
---|
962 | if (maxsize) { |
---|
963 | if (cryst->planegroup < 13) { |
---|
964 | cryst->gamma = 90.0; |
---|
965 | cryst->offset_w = 0; |
---|
966 | cryst->offset_h = 0; |
---|
967 | if (cryst->planegroup < 10) { |
---|
968 | cryst->b = cryst->win_height; |
---|
969 | cryst->a = cryst->win_width; |
---|
970 | } else { |
---|
971 | cryst->b = min(cryst->win_height, cryst->win_width); |
---|
972 | cryst->a = cryst->b; |
---|
973 | } |
---|
974 | } else { |
---|
975 | cryst->gamma = 120.0; |
---|
976 | cryst->a = (int) (cryst->win_width * 2.0 / 3.0); |
---|
977 | cryst->b = cryst->a; |
---|
978 | cryst->offset_h = (int) (cryst->b * 0.25 * |
---|
979 | cos((cryst->gamma - 90) * PI_RAD)); |
---|
980 | cryst->offset_w = (int) (cryst->b * 0.5); |
---|
981 | } |
---|
982 | } else { |
---|
983 | cryst->offset_w = -1; |
---|
984 | while (cryst->offset_w < 4 || (int) (cryst->offset_w - cryst->b * |
---|
985 | sin((cryst->gamma - 90) * PI_RAD)) < 4) { |
---|
986 | cryst->b = NRAND((int) (cryst->win_height / (cos((cryst->gamma - 90) * |
---|
987 | PI_RAD))) - cell_min) + cell_min; |
---|
988 | if (cryst->planegroup > 8) |
---|
989 | cryst->a = cryst->b; |
---|
990 | else |
---|
991 | cryst->a = NRAND(cryst->win_width - cell_min) + cell_min; |
---|
992 | cryst->offset_w = (int) ((cryst->win_width - (cryst->a - cryst->b * |
---|
993 | sin((cryst->gamma - 90) * |
---|
994 | PI_RAD))) / 2.0); |
---|
995 | } |
---|
996 | cryst->offset_h = (int) ((cryst->win_height - cryst->b * cos(( |
---|
997 | cryst->gamma - 90) * PI_RAD)) / 2.0); |
---|
998 | if (!centre) { |
---|
999 | if (cryst->offset_h > 0) |
---|
1000 | cryst->offset_h = NRAND(2 * cryst->offset_h); |
---|
1001 | cryst->offset_w = (int) (cryst->win_width - cryst->a - |
---|
1002 | cryst->b * |
---|
1003 | fabs(sin((cryst->gamma - 90) * PI_RAD))); |
---|
1004 | if (cryst->gamma > 90.0) { |
---|
1005 | if (cryst->offset_w > 0) |
---|
1006 | cryst->offset_w = NRAND(cryst->offset_w) + |
---|
1007 | (int) (cryst->b * sin((cryst->gamma - 90) * PI_RAD)); |
---|
1008 | else |
---|
1009 | cryst->offset_w = (int) (cryst->b * sin((cryst->gamma - 90) * |
---|
1010 | PI_RAD)); |
---|
1011 | } else if (cryst->offset_w > 0) |
---|
1012 | cryst->offset_w = NRAND(cryst->offset_w); |
---|
1013 | else |
---|
1014 | cryst->offset_w = 0; |
---|
1015 | } |
---|
1016 | } |
---|
1017 | |
---|
1018 | size_atom = min((int) ((float) (cryst->a) / 40.) + 1, |
---|
1019 | (int) ((float) (cryst->b) / 40.) + 1); |
---|
1020 | if (MI_SIZE(mi) < size_atom) { |
---|
1021 | if (MI_SIZE(mi) < -size_atom) |
---|
1022 | size_atom = -size_atom; |
---|
1023 | else |
---|
1024 | size_atom = MI_SIZE(mi); |
---|
1025 | } |
---|
1026 | cryst->a = cryst->a / cryst->nx; |
---|
1027 | cryst->b = cryst->b / cryst->ny; |
---|
1028 | if (cryst->unit_cell) { |
---|
1029 | int y_coor1 , y_coor2; |
---|
1030 | |
---|
1031 | if (MI_NPIXELS(mi) > 2) |
---|
1032 | XSetForeground(display, cryst->gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)))); |
---|
1033 | else |
---|
1034 | XSetForeground(display, cryst->gc, MI_WHITE_PIXEL(mi)); |
---|
1035 | if (cryst->grid_cell) { |
---|
1036 | int inx, iny; |
---|
1037 | |
---|
1038 | if ( cryst->invert ) |
---|
1039 | y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h; |
---|
1040 | else |
---|
1041 | y_coor1 = y_coor2 = cryst->offset_h; |
---|
1042 | XDrawLine(display, window, cryst->gc, cryst->offset_w, |
---|
1043 | y_coor1, cryst->offset_w + cryst->nx * cryst->a, |
---|
1044 | y_coor2); |
---|
1045 | if ( cryst->invert ) |
---|
1046 | { |
---|
1047 | y_coor1 = cryst->win_height - cryst->offset_h; |
---|
1048 | y_coor2 = cryst->win_height - (int) (cryst->ny * |
---|
1049 | cryst->b * |
---|
1050 | cos((cryst->gamma - 90) * PI_RAD)) - |
---|
1051 | cryst->offset_h; |
---|
1052 | } |
---|
1053 | else |
---|
1054 | { |
---|
1055 | y_coor1 = cryst->offset_h; |
---|
1056 | y_coor2 = (int) (cryst->ny * cryst->b * |
---|
1057 | cos((cryst->gamma - 90) * PI_RAD)) + |
---|
1058 | cryst->offset_h; |
---|
1059 | } |
---|
1060 | XDrawLine(display, window, cryst->gc, cryst->offset_w, |
---|
1061 | y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b * |
---|
1062 | sin((cryst->gamma - 90) * PI_RAD)), |
---|
1063 | y_coor2); |
---|
1064 | inx = cryst->nx; |
---|
1065 | for (iny = 1; iny <= cryst->ny; iny++) { |
---|
1066 | if ( cryst->invert ) |
---|
1067 | { |
---|
1068 | y_coor1 = cryst->win_height - |
---|
1069 | (int) (iny * cryst->b * cos((cryst->gamma - 90) * |
---|
1070 | PI_RAD)) - cryst->offset_h; |
---|
1071 | y_coor2 = cryst->win_height - |
---|
1072 | (int) (iny * cryst->b * cos((cryst->gamma - 90) * |
---|
1073 | PI_RAD)) - |
---|
1074 | cryst->offset_h; |
---|
1075 | } |
---|
1076 | else |
---|
1077 | { |
---|
1078 | y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * |
---|
1079 | PI_RAD)) + cryst->offset_h; |
---|
1080 | y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) + |
---|
1081 | cryst->offset_h; |
---|
1082 | } |
---|
1083 | XDrawLine(display, window, cryst->gc, |
---|
1084 | (int) (cryst->offset_w + |
---|
1085 | inx * cryst->a - (int) (iny * cryst->b * |
---|
1086 | sin((cryst->gamma - 90) * PI_RAD))), |
---|
1087 | y_coor1, |
---|
1088 | (int) (cryst->offset_w - iny * cryst->b * |
---|
1089 | sin((cryst->gamma - 90) * PI_RAD)), |
---|
1090 | y_coor2); |
---|
1091 | } |
---|
1092 | iny = cryst->ny; |
---|
1093 | for (inx = 1; inx <= cryst->nx; inx++) { |
---|
1094 | if ( cryst->invert ) |
---|
1095 | { |
---|
1096 | y_coor1 =cryst->win_height - |
---|
1097 | (int) (iny * cryst->b * |
---|
1098 | cos((cryst->gamma - 90) * |
---|
1099 | PI_RAD)) - cryst->offset_h; |
---|
1100 | y_coor2 =cryst->win_height - cryst->offset_h; |
---|
1101 | } |
---|
1102 | else |
---|
1103 | { |
---|
1104 | y_coor1 =(int) (iny * cryst->b * |
---|
1105 | cos((cryst->gamma - 90) * |
---|
1106 | PI_RAD)) + cryst->offset_h; |
---|
1107 | y_coor2 =cryst->offset_h; |
---|
1108 | } |
---|
1109 | XDrawLine(display, window, cryst->gc, |
---|
1110 | (int) (cryst->offset_w + |
---|
1111 | inx * cryst->a - (int) (iny * cryst->b * |
---|
1112 | sin((cryst->gamma - 90) * PI_RAD))), |
---|
1113 | y_coor1, |
---|
1114 | cryst->offset_w + inx * cryst->a, |
---|
1115 | y_coor2); |
---|
1116 | } |
---|
1117 | } else { |
---|
1118 | int inx, iny; |
---|
1119 | |
---|
1120 | inx = NRAND(cryst->nx); |
---|
1121 | iny = NRAND(cryst->ny); |
---|
1122 | if ( cryst->invert ) |
---|
1123 | { |
---|
1124 | y_coor1 =cryst->win_height - |
---|
1125 | (int) (iny * cryst->b * |
---|
1126 | cos((cryst->gamma - 90) * |
---|
1127 | PI_RAD)) - |
---|
1128 | cryst->offset_h; |
---|
1129 | y_coor2 =cryst->win_height - |
---|
1130 | (int) ( ( iny + 1 ) * cryst->b * |
---|
1131 | cos((cryst->gamma - 90) * |
---|
1132 | PI_RAD)) - |
---|
1133 | cryst->offset_h; |
---|
1134 | } |
---|
1135 | else |
---|
1136 | { |
---|
1137 | y_coor1 =(int) (iny * cryst->b * |
---|
1138 | cos((cryst->gamma - 90) * |
---|
1139 | PI_RAD)) + |
---|
1140 | cryst->offset_h; |
---|
1141 | y_coor2 =(int) (( iny + 1 ) * cryst->b * |
---|
1142 | cos((cryst->gamma - 90) * |
---|
1143 | PI_RAD)) + |
---|
1144 | cryst->offset_h; |
---|
1145 | } |
---|
1146 | XDrawLine(display, window, cryst->gc, |
---|
1147 | cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1148 | y_coor1, |
---|
1149 | cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1150 | y_coor1); |
---|
1151 | XDrawLine(display, window, cryst->gc, |
---|
1152 | cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1153 | y_coor1, |
---|
1154 | cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1155 | y_coor2); |
---|
1156 | XDrawLine(display, window, cryst->gc, |
---|
1157 | cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1158 | y_coor1, |
---|
1159 | cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1160 | y_coor2); |
---|
1161 | XDrawLine(display, window, cryst->gc, |
---|
1162 | cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1163 | y_coor2, |
---|
1164 | cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)), |
---|
1165 | y_coor2); |
---|
1166 | } |
---|
1167 | } |
---|
1168 | if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { |
---|
1169 | /* Set up colour map */ |
---|
1170 | if (cryst->colors && cryst->ncolors && !cryst->no_colors) |
---|
1171 | free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors); |
---|
1172 | if (cryst->colors) |
---|
1173 | (void) free((void *) cryst->colors); |
---|
1174 | cryst->colors = 0; |
---|
1175 | cryst->ncolors = MI_NCOLORS(mi); |
---|
1176 | if (cryst->ncolors < 2) |
---|
1177 | cryst->ncolors = 2; |
---|
1178 | if (cryst->ncolors <= 2) |
---|
1179 | cryst->mono_p = True; |
---|
1180 | else |
---|
1181 | cryst->mono_p = False; |
---|
1182 | |
---|
1183 | if (cryst->mono_p) |
---|
1184 | cryst->colors = 0; |
---|
1185 | else |
---|
1186 | cryst->colors = (XColor *) malloc(sizeof (*cryst->colors) * (cryst->ncolors + 1)); |
---|
1187 | cryst->cycle_p = has_writable_cells(mi->xgwa.screen, MI_VISUAL(mi)); |
---|
1188 | if (cryst->cycle_p) { |
---|
1189 | if (MI_IS_FULLRANDOM(mi)) { |
---|
1190 | if (!NRAND(8)) |
---|
1191 | cryst->cycle_p = False; |
---|
1192 | else |
---|
1193 | cryst->cycle_p = True; |
---|
1194 | } else { |
---|
1195 | cryst->cycle_p = cycle_p; |
---|
1196 | } |
---|
1197 | } |
---|
1198 | if (!cryst->mono_p) { |
---|
1199 | if (!(LRAND() % 10)) |
---|
1200 | make_random_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors, |
---|
1201 | True, True, &cryst->cycle_p, True); |
---|
1202 | else if (!(LRAND() % 2)) |
---|
1203 | make_uniform_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors, |
---|
1204 | True, &cryst->cycle_p, True); |
---|
1205 | else |
---|
1206 | make_smooth_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors, |
---|
1207 | True, &cryst->cycle_p, True); |
---|
1208 | } |
---|
1209 | #if 0 /* #### wrong! -jwz */ |
---|
1210 | XInstallColormap(display, cryst->cmap); |
---|
1211 | #endif |
---|
1212 | if (cryst->ncolors < 2) { |
---|
1213 | cryst->ncolors = 2; |
---|
1214 | cryst->no_colors = True; |
---|
1215 | } else |
---|
1216 | cryst->no_colors = False; |
---|
1217 | if (cryst->ncolors <= 2) |
---|
1218 | cryst->mono_p = True; |
---|
1219 | |
---|
1220 | if (cryst->mono_p) |
---|
1221 | cryst->cycle_p = False; |
---|
1222 | |
---|
1223 | } |
---|
1224 | for (i = 0; i < cryst->num_atom; i++) { |
---|
1225 | crystalatom *atom0; |
---|
1226 | |
---|
1227 | atom0 = &cryst->atom[i]; |
---|
1228 | if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) { |
---|
1229 | if (cryst->ncolors > 2) |
---|
1230 | atom0->colour = NRAND(cryst->ncolors - 2) + 2; |
---|
1231 | else |
---|
1232 | atom0->colour = 1; /* Just in case */ |
---|
1233 | XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel); |
---|
1234 | } else { |
---|
1235 | if (MI_NPIXELS(mi) > 2) |
---|
1236 | atom0->colour = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))); |
---|
1237 | else |
---|
1238 | atom0->colour = 1; /*Xor'red so WHITE may not be appropriate */ |
---|
1239 | XSetForeground(display, cryst->gc, atom0->colour); |
---|
1240 | } |
---|
1241 | atom0->x0 = NRAND(cryst->a); |
---|
1242 | atom0->y0 = NRAND(cryst->b); |
---|
1243 | atom0->velocity[0] = NRAND(7) - 3; |
---|
1244 | atom0->velocity[1] = NRAND(7) - 3; |
---|
1245 | atom0->velocity_a = (NRAND(7) - 3) * PI_RAD; |
---|
1246 | atom0->angle = NRAND(90) * PI_RAD; |
---|
1247 | atom0->at_type = NRAND(3); |
---|
1248 | if (size_atom == 0) |
---|
1249 | atom0->size_at = DEF_SIZ_ATOM; |
---|
1250 | else if (size_atom > 0) |
---|
1251 | atom0->size_at = size_atom; |
---|
1252 | else |
---|
1253 | atom0->size_at = NRAND(-size_atom) + 1; |
---|
1254 | atom0->size_at++; |
---|
1255 | if (atom0->at_type == 2) |
---|
1256 | atom0->num_point = 3; |
---|
1257 | else |
---|
1258 | atom0->num_point = 4; |
---|
1259 | crystal_setupatom(atom0, cryst->gamma); |
---|
1260 | crystal_drawatom(mi, atom0); |
---|
1261 | } |
---|
1262 | XSync(display, False); |
---|
1263 | XSetFunction(display, cryst->gc, GXcopy); |
---|
1264 | } |
---|