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