1 /* **************************************************************** */
2 /* functions to deal with drawing atoms, etc. */
6 #include <X11/Intrinsic.h>
7 #include <X11/StringDefs.h>
10 #include <X11/Xaw/Label.h>
11 #include <X11/Xaw/Cardinals.h>
17 /* hard offsets so we dont draw on exact edge of screen */
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
,
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 /* **************************************************************** */
46 static GC
*gc
= (GC
*) NULL
;
47 static GC
*bondgc
= (GC
*) NULL
;
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
,
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
);
73 PRIVATE
void SceneDraw(void)
83 static int last_step
= -1;
85 if (!XtIsRealized(Scene
)) return;
92 /* Clear everything */
94 if (Common
.step
>= Common
.ndata
) return;
95 if (Common
.step
< 0) return;
97 XFillRectangle(XtDisplay(Scene
), Buffer
, bggc
, 0, 0,
100 /* XClearWindow(XtDisplay(Scene), XtWindow(Scene)); */
104 dptr
= Common
.dataptr
+ Common
.step
;
106 /* loop over colors */
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
],
115 b
+= dptr
->nbtypes
[i
];
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
,
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);
141 PRIVATE
void MotionUpdate(void)
147 if (Common
.saveflag
) {
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
);
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
) {
167 Common
.step
= next_step
;
169 TimeOut
= (XtIntervalId
) NULL
;
174 void SceneUpdate(void)
177 if (!Common
.init
) return;
179 /* Common.step = CoerceStep(Common.step); */
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);
198 void ExposeScene(Widget w
, XEvent
*event
, String
*strings
,
206 void InstallMotion(void)
210 if (TimeOut
== (XtIntervalId
) NULL
)
211 TimeOut
= XtAppAddTimeOut(XtWidgetToApplicationContext(Scene
),
213 (XtTimerCallbackProc
) MotionUpdate
, NULL
);
216 void RemoveMotion(void)
218 if (!Common
.motion
) return;
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
,
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 */
249 if (*npoints
> max_points
) {
250 XtFree((char *) points
);
251 points
= (POINT
*) XtMalloc( *npoints
* sizeof(POINT
));
252 max_points
= *npoints
;
256 if (cnt
< 1) return(points
);
258 SceneSize(&width
, &height
);
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;
271 (pos
->z
* Common
.scale
+ Common
.offset
[2]);
273 (pos
->y
* Common
.scale
+ Common
.offset
[1]);
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];
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];
296 (pos
->y
* Common
.scale
+ Common
.offset
[1]);
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];
308 (pos
->y
* Common
.scale
+ Common
.offset
[1]);
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];
321 (pos
->z
* Common
.scale
+ Common
.offset
[2]);
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];
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;
356 PRIVATE
void DrawPoints(Display
*display
, Drawable drawable
, GC gc
,
357 POINT
*points
, int npoints
)
359 register int full_circle
;
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
++){
372 p
->angle2
= full_circle
;
377 XFillArcs(display
, drawable
, bggc
, points
, npoints
);
378 XDrawArcs(display
, drawable
, gc
, points
, npoints
);
381 XFillArcs(display
, drawable
, gc
, points
, npoints
);
385 PRIVATE LINE
*ClipAndScaleLines(BOND
*bond
, int cnt
, int *nlines
)
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 */
401 if (*nlines
> max_lines
) {
402 XtFree((char *) lines
);
403 lines
= (LINE
*) XtMalloc( *nlines
* sizeof(LINE
));
408 if (cnt
< 1) return(lines
);
410 SceneSize(&width
, &height
);
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;
424 (bond
->atom1
->z
*Common
.scale
+Common
.offset
[2]);
426 (bond
->atom1
->y
*Common
.scale
+Common
.offset
[1]);
428 (bond
->atom2
->z
*Common
.scale
+Common
.offset
[2]);
430 (bond
->atom2
->y
*Common
.scale
+Common
.offset
[1]);
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];
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];
455 (bond
->atom1
->y
*Common
.scale
+Common
.offset
[1]);
456 l
->x2
= bond
->atom2
->x
*Common
.scale
+ Common
.offset
[0];
458 (bond
->atom2
->y
*Common
.scale
+Common
.offset
[1]);
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];
470 (bond
->atom1
->y
*Common
.scale
+Common
.offset
[1]);
471 l
->x2
= bond
->atom2
->z
*Common
.scale
+ Common
.offset
[2];
473 (bond
->atom2
->y
*Common
.scale
+Common
.offset
[1]);
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];
486 (bond
->atom1
->z
*Common
.scale
+Common
.offset
[2]);
487 l
->x2
= bond
->atom2
->x
*Common
.scale
+ Common
.offset
[0];
489 (bond
->atom2
->z
*Common
.scale
+Common
.offset
[2]);
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];
512 /* add the hard offsets so we dont draw on edge of screen */
514 for(i
= *nlines
, l
= lines
; i
; i
--, l
++) {
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
);
540 void NewDataSetup(void)
542 static int have_pixmap
= 0;
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
)));
559 /* determine global scaling and offset factors */
560 /* offset + scale * coordinate = pixel */
563 for(i
= 3, cb
= Common
.bounds
; i
; i
--, cb
++)
564 if ((f
= (cb
->high
) - (cb
->low
)) > longest
) longest
= f
;
566 SceneSize(&Width
, &Height
);
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
;
582 /* **************************************************************** */
584 void SetAtomColors(Pixel
*fg
)
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
)
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
)
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
,
644 /* **************************************************************** */
646 PRIVATE
void SetAllColors(void)
651 xgc
.function
= GXcopy
;
655 XtNbackground
, &xgc
.background
,
656 XtNforeground
, &xgc
.foreground
,
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
,
668 xgc
.foreground
= xgc
.background
;
669 bggc
= XCreateGC(XtDisplay(Scene
), XtWindow(Scene
),
670 GCFunction
| GCBackground
| GCForeground
, &xgc
);