git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@16053 f3b2605a-c512-4ea7-a41b...
[lammps.git] / tools / xmovie / scene.c
blobe021aa580f479b1aabf2b7dca2f0022a741ef0a9
1 /* **************************************************************** */
2 /* functions to deal with drawing atoms, etc. */
4 #include <stdio.h>
6 #include <X11/Intrinsic.h>
7 #include <X11/StringDefs.h>
8 #include <X11/Shell.h>
10 #include <X11/Xaw/Label.h>
11 #include <X11/Xaw/Cardinals.h>
13 #include <X11/xpm.h>
15 #include "xmovie.h"
17 /* hard offsets so we dont draw on exact edge of screen */
19 #define HOFFSET 5
20 #define VOFFSET 5
22 typedef XArc POINT;
23 typedef XSegment LINE;
25 /* **************************************************************** */
26 /* local prototypes */
28 PRIVATE LINE *ClipAndScaleLines(BOND *b, int cnt, int *nlines);
29 PRIVATE POINT *ClipAndScalePoints(POSITION *p, int cnt, Dimension diam,
30 int *npoints);
31 PRIVATE void DrawPoints(Display *display, Drawable drawable, GC gc,
32 POINT *points, int npoints);
33 PRIVATE void DrawLines(Display *display, Drawable drawable, GC gc,
34 LINE *lines, int nlines);
35 PRIVATE void SceneDraw(void);
36 PRIVATE void SetAllColors(void);
37 PRIVATE void MotionUpdate(void);
39 /* **************************************************************** */
40 /* local data */
42 static Widget Scene;
43 static Widget Shell;
44 static Pixmap Buffer;
46 static GC *gc = (GC *) NULL;
47 static GC *bondgc = (GC *) NULL;
48 static GC bggc;
49 static int first = 1;
50 static Dimension Height, Width;
52 XtIntervalId TimeOut = (XtIntervalId) NULL;
53 static String null_string = "";
55 /* **************************************************************** */
57 Widget CreateScene(Widget parent, char *name)
59 Shell = XtCreatePopupShell("sceneshell", transientShellWidgetClass,
60 parent, NULL, ZERO);
62 Scene = XtVaCreateManagedWidget(name, labelWidgetClass, Shell,
63 XtNlabel, &null_string, NULL);
65 gc = (GC *) XtMalloc(Common.natomcolors * sizeof(GC));
66 bondgc = (GC *) XtMalloc(Common.nbondcolors * sizeof(GC));
68 XtPopup(Shell, XtGrabNone);
70 return(Scene);
73 PRIVATE void SceneDraw(void)
75 DATA *dptr;
76 POINT *points;
77 LINE *lines;
78 POSITION *p;
79 BOND *b;
80 int i;
81 int npoints, nlines;
82 char s[40];
83 static int last_step = -1;
85 if (!XtIsRealized(Scene)) return;
87 if (first) {
88 SetAllColors();
89 first = 0;
92 /* Clear everything */
94 if (Common.step >= Common.ndata) return;
95 if (Common.step < 0) return;
97 XFillRectangle(XtDisplay(Scene), Buffer, bggc, 0, 0,
98 Width, Height);
100 /* XClearWindow(XtDisplay(Scene), XtWindow(Scene)); */
102 /* find the data */
104 dptr = Common.dataptr + Common.step;
106 /* loop over colors */
108 b = dptr->bonds;
109 for(i = 0; i < Common.nbondcolors; i++) {
110 if (Common.bonds_visible[i]) {
111 lines = ClipAndScaleLines(b, dptr->nbtypes[i],&nlines);
112 DrawLines(XtDisplay(Scene), Buffer, bondgc[i],
113 lines, nlines);
115 b += dptr->nbtypes[i];
118 p = dptr->positions;
119 for(i = 0; i < Common.natomcolors; i++){
120 if (Common.atoms_visible[i]) {
121 points = ClipAndScalePoints(p, dptr->natypes[i],
122 Common.diameter[i], &npoints);
123 DrawPoints(XtDisplay(Scene), Buffer, gc[i], points,
124 npoints);
126 p += dptr->natypes[i];
129 XCopyArea(XtDisplay(Scene), Buffer, XtWindow(Scene), bggc,
130 0, 0, Width, Height, 0, 0);
132 XFlush(XtDisplay(Scene));
134 if (Common.step == last_step) return;
135 last_step = Common.step;
137 sprintf(s,"Time: %g Frame: %i", dptr->time, Common.step+1);
138 SetTime(s);
141 PRIVATE void MotionUpdate(void)
143 int next_step;
145 SceneUpdate();
147 if (Common.saveflag) {
148 char str[24];
149 if (Common.step < 10)
150 sprintf(str,"image00%d.xpm",Common.step);
151 else if (Common.step < 100)
152 sprintf(str,"image0%d.xpm",Common.step);
153 else
154 sprintf(str,"image%d.xpm",Common.step);
155 XpmWriteFileFromPixmap(XtDisplay(Scene),str,Buffer,NULL,NULL);
158 if (!Common.motion) return;
160 next_step = CoerceStep(Common.step + Common.dstep);
162 if (next_step == Common.step) {
163 RemoveMotion();
164 return;
167 Common.step = next_step;
169 TimeOut = (XtIntervalId) NULL;
171 InstallMotion();
174 void SceneUpdate(void)
177 if (!Common.init) return;
179 /* Common.step = CoerceStep(Common.step); */
181 SceneDraw();
184 void SceneSave(void)
186 char str[24];
187 sprintf(str,"image.%d.xpm",Common.step);
188 XpmWriteFileFromPixmap(XtDisplay(Scene),str,Buffer,NULL,NULL);
191 int CoerceStep(int step)
193 if (step >= Common.ndata) return (Common.ndata-1);
194 if (step < 0) return(0);
195 return(step);
198 void ExposeScene(Widget w, XEvent *event, String *strings,
199 Cardinal *nstrings)
201 NewDataSetup();
202 SceneDraw();
206 void InstallMotion(void)
208 Common.motion = 1;
210 if (TimeOut == (XtIntervalId) NULL)
211 TimeOut = XtAppAddTimeOut(XtWidgetToApplicationContext(Scene),
212 Common.delay,
213 (XtTimerCallbackProc) MotionUpdate, NULL);
216 void RemoveMotion(void)
218 if (!Common.motion) return;
220 Common.motion = 0;
221 Common.step = CoerceStep(Common.step - Common.dstep);
223 if (TimeOut != (XtIntervalId) NULL) XtRemoveTimeOut(TimeOut);
224 TimeOut = (XtIntervalId) NULL;
227 void SceneSize(Dimension *width, Dimension *height)
229 XtVaGetValues(Scene, XtNwidth, width, XtNheight, height, NULL);
232 PRIVATE POINT *ClipAndScalePoints(POSITION *pos, int cnt, Dimension diam,
233 int *npoints)
235 register int i;
236 BOUND range;
237 register POINT *p;
238 Dimension width, height;
239 static int max_points = 0;
240 static POINT *points = (POINT *) NULL;
242 range.low = Common.position - Common.thickness * 0.5;
243 range.high = Common.position + Common.thickness * 0.5;
245 /* use a static buffer so minimize number of allocations */
246 /* didnt use Realloc because dont want data copied */
248 *npoints = cnt;
249 if (*npoints > max_points) {
250 XtFree((char *) points);
251 points = (POINT *) XtMalloc( *npoints * sizeof(POINT));
252 max_points = *npoints;
254 p = points;
256 if (cnt < 1) return(points);
258 SceneSize(&width, &height);
259 width -= 2*HOFFSET;
260 height -= 2*VOFFSET;
262 /* translate x, y, z to x and y in window. */
263 /* note: index and type are also passed, but may not be used */
265 switch(3*Common.direction + Common.axis){
266 case 0: /* negative direction, x axis */
267 for(i = cnt; i; i--, pos++) {
268 if (pos->x > range.high) continue;
269 if (pos->x < range.low) continue;
270 p->x = width -
271 (pos->z * Common.scale + Common.offset[2]);
272 p->y = height -
273 (pos->y * Common.scale + Common.offset[1]);
274 p->width = diam;
275 p->height = diam;
276 p++;
278 break;
279 case 1: /* negative direction, y axis */
280 for(i = cnt; i; i--, pos++) {
281 if (pos->y > range.high) continue;
282 if (pos->y < range.low) continue;
283 p->x = pos->x * Common.scale + Common.offset[0];
284 p->y = pos->z * Common.scale + Common.offset[2];
285 p->width = diam;
286 p->height = diam;
287 p++;
289 break;
290 case 2: /* negative direction, z axis */
291 for(i = cnt; i; i--, pos++) {
292 if (pos->z > range.high) continue;
293 if (pos->z < range.low) continue;
294 p->x = pos->x * Common.scale + Common.offset[0];
295 p->y = height -
296 (pos->y * Common.scale + Common.offset[1]);
297 p->width = diam;
298 p->height = diam;
299 p++;
301 break;
302 case 3: /* positive direction, x axis */
303 for(i = cnt; i; i--, pos++) {
304 if (pos->x > range.high) continue;
305 if (pos->x < range.low) continue;
306 p->x = pos->z * Common.scale + Common.offset[2];
307 p->y = height -
308 (pos->y * Common.scale + Common.offset[1]);
309 p->width = diam;
310 p->height = diam;
311 p++;
313 break;
315 case 4: /* positive direction, y axis */
316 for(i = cnt; i; i--, pos++) {
317 if (pos->y > range.high) continue;
318 if (pos->y < range.low) continue;
319 p->x = pos->x * Common.scale + Common.offset[0];
320 p->y = height -
321 (pos->z * Common.scale + Common.offset[2]);
322 p->width = diam;
323 p->height = diam;
324 p++;
326 break;
329 case 5: /* postive direction, z axis */
330 for(i = cnt; i; i--, pos++) {
331 if (pos->z > range.high) continue;
332 if (pos->z < range.low) continue;
333 p->x = pos->x * Common.scale + Common.offset[0];
334 p->y = pos->y * Common.scale + Common.offset[1];
335 p->width = diam;
336 p->height = diam;
337 p++;
339 break;
342 *npoints = p - points;
344 /* add the hard offsets so we dont draw on edge of screen */
345 /* center drawing based on width, height */
347 for(i = *npoints, p = points; i; i--, p++) {
348 p->x += HOFFSET - p->width/2;
349 p->y += VOFFSET - p->height/2;
352 return(points);
356 PRIVATE void DrawPoints(Display *display, Drawable drawable, GC gc,
357 POINT *points, int npoints)
359 register int full_circle;
360 register int i;
361 register POINT *p;
363 if (npoints <= 0) return;
365 /* this version has POINT typedef'd to XArc, so we need to */
366 /* fill in other fields before drawing */
368 full_circle = 64*360;
370 for(i = npoints, p = points; i ; i--, p++){
371 p->angle1 = 0;
372 p->angle2 = full_circle;
375 if (Common.hollow) {
376 if (Common.opaque)
377 XFillArcs(display, drawable, bggc, points, npoints);
378 XDrawArcs(display, drawable, gc, points, npoints);
380 else
381 XFillArcs(display, drawable, gc, points, npoints);
385 PRIVATE LINE *ClipAndScaleLines(BOND *bond, int cnt, int *nlines)
387 register int i;
388 BOUND range;
389 register LINE *l;
390 Dimension width, height;
391 static int max_lines = 0;
392 static LINE *lines = (LINE *) NULL;
394 range.low = Common.position - Common.thickness * 0.5;
395 range.high = Common.position + Common.thickness * 0.5;
397 /* use a static buffer so minimize number of allocations */
398 /* didnt use Realloc because dont want data copied */
400 *nlines = cnt;
401 if (*nlines > max_lines) {
402 XtFree((char *) lines);
403 lines = (LINE *) XtMalloc( *nlines * sizeof(LINE));
404 max_lines = *nlines;
406 l = lines;
408 if (cnt < 1) return(lines);
410 SceneSize(&width, &height);
411 width -= 2*HOFFSET;
412 height -= 2*VOFFSET;
414 /* translate x, y, z to x and y in window. */
416 switch(3*Common.direction + Common.axis){
417 case 0: /* negative direction, x axis */
418 for(i = cnt; i; i--, bond++) {
419 if (bond->atom1->x > range.high) continue;
420 if (bond->atom1->x < range.low) continue;
421 if (bond->atom2->x > range.high) continue;
422 if (bond->atom2->x < range.low) continue;
423 l->x1 = width -
424 (bond->atom1->z*Common.scale+Common.offset[2]);
425 l->y1 = height -
426 (bond->atom1->y*Common.scale+Common.offset[1]);
427 l->x2 = width -
428 (bond->atom2->z*Common.scale+Common.offset[2]);
429 l->y2 = height -
430 (bond->atom2->y*Common.scale+Common.offset[1]);
431 l++;
433 break;
434 case 1: /* negative direction, y axis */
435 for(i = cnt; i; i--, bond++) {
436 if (bond->atom1->y > range.high) continue;
437 if (bond->atom1->y < range.low) continue;
438 if (bond->atom2->y > range.high) continue;
439 if (bond->atom2->y < range.low) continue;
440 l->x1 = bond->atom1->x*Common.scale + Common.offset[0];
441 l->y1 = bond->atom1->z*Common.scale + Common.offset[2];
442 l->x2 = bond->atom2->x*Common.scale + Common.offset[0];
443 l->y2 = bond->atom2->z*Common.scale + Common.offset[2];
444 l++;
446 break;
447 case 2: /* negative direction, z axis */
448 for(i = cnt; i; i--, bond++) {
449 if (bond->atom1->z > range.high) continue;
450 if (bond->atom1->z < range.low) continue;
451 if (bond->atom2->z > range.high) continue;
452 if (bond->atom2->z < range.low) continue;
453 l->x1 = bond->atom1->x*Common.scale + Common.offset[0];
454 l->y1 = height -
455 (bond->atom1->y*Common.scale+Common.offset[1]);
456 l->x2 = bond->atom2->x*Common.scale + Common.offset[0];
457 l->y2 = height -
458 (bond->atom2->y*Common.scale+Common.offset[1]);
459 l++;
461 break;
462 case 3: /* positive direction, x axis */
463 for(i = cnt; i; i--, bond++) {
464 if (bond->atom1->x > range.high) continue;
465 if (bond->atom1->x < range.low) continue;
466 if (bond->atom2->x > range.high) continue;
467 if (bond->atom2->x < range.low) continue;
468 l->x1 = bond->atom1->z*Common.scale + Common.offset[2];
469 l->y1 = height -
470 (bond->atom1->y*Common.scale+Common.offset[1]);
471 l->x2 = bond->atom2->z*Common.scale + Common.offset[2];
472 l->y2 = height -
473 (bond->atom2->y*Common.scale+Common.offset[1]);
474 l++;
476 break;
478 case 4: /* positive direction, y axis */
479 for(i = cnt; i; i--, bond++) {
480 if (bond->atom1->y > range.high) continue;
481 if (bond->atom1->y < range.low) continue;
482 if (bond->atom2->y > range.high) continue;
483 if (bond->atom2->y < range.low) continue;
484 l->x1 = bond->atom1->x*Common.scale + Common.offset[0];
485 l->y1 = height -
486 (bond->atom1->z*Common.scale+Common.offset[2]);
487 l->x2 = bond->atom2->x*Common.scale + Common.offset[0];
488 l->y2 = height -
489 (bond->atom2->z*Common.scale+Common.offset[2]);
490 l++;
492 break;
495 case 5: /* postive direction, z axis */
496 for(i = cnt; i; i--, bond++) {
497 if (bond->atom1->z > range.high) continue;
498 if (bond->atom1->z < range.low) continue;
499 if (bond->atom2->z > range.high) continue;
500 if (bond->atom2->z < range.low) continue;
501 l->x1 = bond->atom1->x*Common.scale + Common.offset[0];
502 l->y1 = bond->atom1->y*Common.scale + Common.offset[1];
503 l->x2 = bond->atom2->x*Common.scale + Common.offset[0];
504 l->y2 = bond->atom2->y*Common.scale + Common.offset[1];
505 l++;
507 break;
510 *nlines = l - lines;
512 /* add the hard offsets so we dont draw on edge of screen */
514 for(i = *nlines, l = lines; i; i--, l++) {
515 l->x1 += HOFFSET;
516 l->y1 += VOFFSET;
517 l->x2 += HOFFSET;
518 l->y2 += VOFFSET;
521 return(lines);
525 PRIVATE void DrawLines(Display *display, Drawable drawable, GC gc,
526 LINE *lines, int nlines)
528 if (nlines <= 0) return;
530 XDrawSegments(display, drawable, gc, lines, nlines);
533 void Setup(void)
535 NewDataSetup();
536 SpeedUpdate();
537 UpdateRadios();
540 void NewDataSetup(void)
542 static int have_pixmap = 0;
544 BOUND *cb;
545 int i;
546 float longest, f;
547 Dimension width, height;
549 SceneSize(&Width, &Height);
551 if (have_pixmap) XFreePixmap(XtDisplay(Scene), Buffer);
553 Buffer = XCreatePixmap(XtDisplay(Scene),
554 RootWindowOfScreen(XtScreen(Scene)), Width, Height,
555 DefaultDepthOfScreen(XtScreen(Scene)));
557 have_pixmap = 1;
559 /* determine global scaling and offset factors */
560 /* offset + scale * coordinate = pixel */
562 longest = 0.0;
563 for(i = 3, cb = Common.bounds; i ; i--, cb++)
564 if ((f = (cb->high) - (cb->low)) > longest) longest = f;
566 SceneSize(&Width, &Height);
567 width = Width;
568 height = Height;
570 width -= HOFFSET*2;
571 height -= VOFFSET*2;
573 Common.scale = (width < height) ? width/longest : height/longest;
575 for(i = 0; i < 3; i++)
576 Common.offset[i] = - Common.bounds[i].low * Common.scale;
578 PositionUpdate();
579 ThicknessUpdate();
582 /* **************************************************************** */
584 void SetAtomColors(Pixel *fg)
586 int i;
587 XGCValues xgc;
589 XtVaGetValues(Scene, XtNbackground, &xgc.background, NULL);
591 xgc.function = GXcopy;
593 for(i = 0; i < Common.natomcolors; i++) {
594 if (gc[i]) XFreeGC(XtDisplay(Scene), gc[i]);
595 xgc.foreground = fg[i];
596 gc[i] = XCreateGC(XtDisplay(Scene), XtWindow(Scene),
597 GCFunction | GCBackground | GCForeground, &xgc);
600 if (bggc) XFreeGC(XtDisplay(Scene), bggc);
601 xgc.foreground = xgc.background;
602 bggc = XCreateGC(XtDisplay(Scene), XtWindow(Scene),
603 GCFunction | GCBackground | GCForeground, &xgc);
607 void SetBGColor(Pixel bg)
609 XGCValues xgc;
611 XtVaSetValues(Scene, XtNbackground, bg, NULL);
613 if (bggc) XFreeGC(XtDisplay(Scene), bggc);
615 xgc.function = GXcopy;
616 xgc.foreground = xgc.background = bg;
618 bggc = XCreateGC(XtDisplay(Scene), XtWindow(Scene),
619 GCFunction | GCBackground | GCForeground, &xgc);
623 /* **************************************************************** */
625 void SetBondColors(Pixel *fg, Dimension *thick)
627 int i;
628 XGCValues xgc;
630 XtVaGetValues(Scene, XtNbackground, &xgc.background, NULL);
632 xgc.function = GXcopy;
634 for(i = 0; i < Common.nbondcolors; i++) {
635 if (bondgc[i]) XFreeGC(XtDisplay(Scene), bondgc[i]);
636 xgc.foreground = fg[i];
637 xgc.line_width = thick[i];
638 bondgc[i] = XCreateGC(XtDisplay(Scene), XtWindow(Scene),
639 GCFunction | GCBackground | GCForeground | GCLineWidth,
640 &xgc);
644 /* **************************************************************** */
646 PRIVATE void SetAllColors(void)
648 int i;
649 XGCValues xgc;
651 xgc.function = GXcopy;
652 xgc.line_width = 1;
654 XtVaGetValues(Scene,
655 XtNbackground, &xgc.background,
656 XtNforeground, &xgc.foreground,
657 NULL);
659 for(i = 0; i < Common.natomcolors; i++)
660 gc[i] = XCreateGC(XtDisplay(Scene), XtWindow(Scene),
661 GCFunction | GCBackground | GCForeground, &xgc);
663 for(i = 0; i < Common.nbondcolors; i++)
664 bondgc[i] = XCreateGC(XtDisplay(Scene), XtWindow(Scene),
665 GCFunction | GCBackground | GCForeground | GCLineWidth,
666 &xgc);
668 xgc.foreground = xgc.background;
669 bggc = XCreateGC(XtDisplay(Scene), XtWindow(Scene),
670 GCFunction | GCBackground | GCForeground, &xgc);