4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_nmol_c = "$Id$";
49 static bool MWCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
57 letter.type=ClientMessage;
58 letter.xclient.display=x11->disp;
59 letter.xclient.window=To;
60 letter.xclient.message_type=0;
61 letter.xclient.format=32;
64 /* Do Not draw anything, but signal parent instead, he will
67 letter.xclient.data.l[0]=IDDRAWMOL;
68 letter.xclient.data.l[1]=Button1;
69 XSendEvent(x11->disp,To,True,0,&letter);
73 printf("Molwindow: Buttonpress\n");
75 letter.xclient.data.l[0]=IDLABEL;
76 letter.xclient.data.l[1]=(long)event->xbutton.button;
77 letter.xclient.data.l[2]=event->xbutton.x;
78 letter.xclient.data.l[3]=event->xbutton.y;
79 XSendEvent(x11->disp,To,True,0,&letter);
82 mw->wd.width=event->xconfigure.width;
83 mw->wd.height=event->xconfigure.height;
91 void set_def (t_molwin *mw,matrix box)
93 mw->bShowHydrogen=TRUE;
96 mw->realbox=TRICLINIC(box) ? esbTri : esbRect;
99 t_molwin *init_mw(t_x11 *x11,Window Parent,
100 int x,int y,int width,int height,
101 unsigned long fg,unsigned long bg,
109 InitWin(&mw->wd,x,y,width,height,1,"Mol Window");
111 mw->wd.Parent=Parent;
112 mw->wd.self=XCreateSimpleWindow(x11->disp,Parent,x,y,width,height,1,fg,bg);
113 x11->RegisterCallback(x11,mw->wd.self,Parent,MWCallBack,mw);
114 x11->SetInputMask(x11,mw->wd.self,
115 ExposureMask | StructureNotifyMask |
120 void map_mw(t_x11 *x11,t_molwin *mw)
122 XMapWindow(x11->disp,mw->wd.self);
125 bool toggle_hydrogen(t_x11 *x11,t_molwin *mw)
127 mw->bShowHydrogen=!mw->bShowHydrogen;
128 ExposeWin(x11->disp,mw->wd.self);
130 return mw->bShowHydrogen;
133 void set_bond_type(t_x11 *x11,t_molwin *mw,int bt)
135 if (bt != mw->bond_type) {
137 ExposeWin(x11->disp,mw->wd.self);
141 void set_box_type (t_x11 *x11,t_molwin *mw,int bt)
144 fprintf(stderr,"mw->boxtype = %d, bt = %d\n",mw->boxtype,bt);
146 if (bt != mw->boxtype) {
147 if ((((bt == esbTrunc) || (bt == esbTri)) &&
148 (mw->realbox == esbTri)) || (bt == esbNone)) {
150 ExposeWin(x11->disp,mw->wd.self);
153 fprintf(stderr,"Can not change rectangular box to triclinic or truncated octahedron\n");
157 void done_mw(t_x11 *x11,t_molwin *mw)
159 x11->UnRegisterCallback(x11,mw->wd.self);
163 static void draw_atom(Display *disp,Window w,GC gc,
164 atom_id ai,iv2 vec2[],unsigned long col[],int size[],
165 bool bBall,bool bPlus)
171 XSetForeground(disp,gc,col[ai]);
173 XFillCircle(disp,w,gc,xi,yi,size[ai]-1);
174 XSetForeground(disp,gc,BLACK);
175 XDrawCircle(disp,w,gc,xi,yi,size[ai]);
176 /* XSetForeground(disp,gc,WHITE);
177 XFillCircle(disp,w,gc,xi+4,yi-4,4); */
180 XDrawLine(disp,w,gc,xi-MSIZE,yi,xi+MSIZE+1,yi);
181 XDrawLine(disp,w,gc,xi,yi-MSIZE,xi,yi+MSIZE+1);
184 XDrawLine(disp,w,gc,xi-1,yi,xi+1,yi);
188 /* Global variables */
189 static rvec gl_fbox,gl_hbox,gl_mhbox;
191 static void my_init_pbc(matrix box)
195 for(i=0; (i<DIM); i++) {
196 gl_fbox[i] = box[i][i];
197 gl_hbox[i] = gl_fbox[i]*0.5;
198 gl_mhbox[i] = -gl_hbox[i];
202 static bool local_pbc_dx(rvec x1, rvec x2)
207 for(i=0; (i<DIM); i++) {
211 else if (dx <= gl_mhbox[i])
217 static void draw_bond(Display *disp,Window w,GC gc,
218 atom_id ai,atom_id aj,iv2 vec2[],
219 rvec x[],unsigned long col[],int size[],bool bBalls)
226 draw_atom(disp,w,gc,ai,vec2,col,size,TRUE,FALSE);
227 draw_atom(disp,w,gc,aj,vec2,col,size,TRUE,FALSE);
230 if (local_pbc_dx(x[ai],x[aj])) {
242 XSetForeground(disp,gc,ic);
243 XDrawLine(disp,w,gc,xi,yi,xm,ym);
244 XSetForeground(disp,gc,jc);
245 XDrawLine(disp,w,gc,xm,ym,xj,yj);
248 XSetForeground(disp,gc,ic);
249 XDrawLine(disp,w,gc,xi,yi,xj,yj);
255 int compare_obj(const void *a,const void *b)
273 void create_visibility(t_manager *man)
278 for(i=0,obj=man->obj; (i<man->nobj); i++,obj++)
279 if (obj->eV != eVHidden) {
280 man->bVis[obj->ai]=TRUE;
284 man->bVis[obj->aj]=TRUE;
292 void z_fill(t_manager *man, real *zz)
297 for(i=0,obj=man->obj; (i<man->nobj); i++,obj++)
300 obj->z = zz[obj->ai];
304 obj->z = (zz[obj->ai] + zz[obj->aj]) * 0.5;
311 int filter_vis(t_manager *man)
313 int i,nobj,nvis,nhide;
325 for(i=0; (i<nobj); i++,obj++) {
329 if (obj->eO != eOSingle)
334 newobj[nhide--]=*obj;
342 void draw_objects(Display *disp,Window w,GC gc,int nobj,
343 t_object objs[],iv2 vec2[],rvec x[],
344 unsigned long col[],int size[],bool bShowHydro,int bond_type,
354 XSetLineAttributes(disp,gc,1,LineSolid,CapNotLast,JoinRound);
357 XSetLineAttributes(disp,gc,3,LineSolid,CapNotLast,JoinRound);
360 XSetLineAttributes(disp,gc,5,LineSolid,CapNotLast,JoinRound);
367 fatal_error(0,"Invalid bond_type selected: %d\n",bond_type);
370 for(i=0; (i<nobj); i++) {
374 draw_atom(disp,w,gc,obj->ai,vec2,col,size,bBalls,bPlus);
377 draw_bond(disp,w,gc,obj->ai,obj->aj,vec2,x,col,size,bBalls);
381 draw_bond(disp,w,gc,obj->ai,obj->aj,vec2,x,col,size,bBalls);
387 XSetLineAttributes(disp,gc,1,LineSolid,CapNotLast,JoinRound);
390 static void v4_to_iv2(vec4 x4,iv2 v2,int x0,int y0,real sx,real sy)
395 v2[XX]=x0+sx*x4[XX]*inv_z;
396 v2[YY]=y0-sy*x4[YY]*inv_z;
399 static void draw_box(t_x11 *x11,Window w,t_3dview *view,matrix box,
400 int x0,int y0,real sx,real sy,int boxtype)
403 { 0,0,0 }, { 1,0,0 }, { 1,1,0 }, { 0,1,0 },
404 { 0,0,1 }, { 1,0,1 }, { 1,1,1 }, { 0,1,1 }
406 int tr_bonds[12][2] = {
407 { 0,1 }, { 1,2 }, { 2,3 }, { 3,0 },
408 { 4,5 }, { 5,6 }, { 6,7 }, { 7,4 },
409 { 0,4 }, { 1,5 }, { 2,6 }, { 3,7 }
411 static int *edge=NULL;
413 rvec corner[NCUCEDGE],box_center;
415 iv2 vec2[NCUCEDGE],tv2;
417 calc_box_center(box,box_center);
418 if (boxtype == esbTrunc) {
419 calc_compact_unitcell_vertices(box,corner);
421 edge = compact_unitcell_edges();
423 for(i=0; (i<NCUCEDGE); i++) {
424 m4_op(view->proj,corner[i],x4);
425 v4_to_iv2(x4,vec2[i],x0,y0,sx,sy);
427 XSetForeground(x11->disp,x11->gc,YELLOW);
428 for (i=0; i<NCUCEDGE; i++) {
431 XDrawLine(x11->disp,w,x11->gc,
432 vec2[i0][XX],vec2[i0][YY],vec2[i1][XX],vec2[i1][YY]);
436 if (boxtype == esbRect)
437 for(j=0; (j<DIM); j++)
438 box_center[j] -= 0.5*box[j][j];
440 for(i=0; (i<DIM); i++)
441 for(j=0; (j<DIM); j++)
442 box_center[j] -= 0.5*box[i][j];
443 for (i=0; (i<8); i++) {
444 clear_rvec(corner[i]);
445 for (j=0; (j<DIM); j++) {
446 if (boxtype == esbTri) {
447 for (k=0; (k<DIM); k++)
448 corner[i][k] += rect_tri[i][j]*box[j][k];
451 corner[i][j] = rect_tri[i][j]*box[j][j];
453 rvec_inc(corner[i],box_center);
454 m4_op(view->proj,corner[i],x4);
455 v4_to_iv2(x4,vec2[i],x0,y0,sx,sy);
458 pr_rvecs(debug,0,"box",box,DIM);
459 pr_rvecs(debug,0,"corner",corner,8);
461 XSetForeground(x11->disp,x11->gc,YELLOW);
462 for (i=0; (i<12); i++) {
465 XDrawLine(x11->disp,w,x11->gc,
466 vec2[i0][XX],vec2[i0][YY],vec2[i1][XX],vec2[i1][YY]);
471 void set_sizes(t_manager *man,real sx,real sy)
475 for(i=0; (i<man->natom); i++)
477 man->size[i]=180*man->vdw[i];
480 void draw_mol(t_x11 *x11,t_manager *man)
482 static char tstr[2][20];
492 if (man->status == -1)
503 sx=win->width/2*view->sc_x;
504 sy=win->height/2*view->sc_y;
506 my_init_pbc(man->box);
508 /* create_visibility(man); */
510 for(i=0; (i<man->natom); i++) {
512 m4_op(view->proj,man->x[i],x4);
514 v4_to_iv2(x4,vec2[i],x0,y0,sx,sy);
517 set_sizes(man,sx,sy);
519 z_fill (man,man->zz);
522 XClearWindow(x11->disp,win->self);
525 sprintf(tstr[ntime],"Time: %.3f ps",man->time);
526 if (strcmp(tstr[ntime],tstr[1-ntime]) != 0) {
527 set_vbtime(x11,man->vbox,tstr[ntime]);
531 if (mw->boxtype != esbNone)
532 draw_box(x11,win->self,view,man->box,x0,y0,sx,sy,mw->boxtype);
534 /* Should sort on Z-Coordinates here! */
535 nvis=filter_vis(man);
536 if (nvis && man->bSort)
537 qsort(man->obj,nvis,sizeof(man->obj[0]),compare_obj);
539 /* Draw the objects */
540 draw_objects(x11->disp,win->self,x11->gc,
541 nvis,man->obj,man->ix,man->x,man->col,man->size,
542 mw->bShowHydrogen,mw->bond_type,man->bPlus);
544 /* Draw the labels */
545 XSetForeground(x11->disp,x11->gc,WHITE);
546 for(i=0; (i<man->natom); i++) {
547 if (man->bLabel[i] && man->bVis[i]) {
548 XDrawString(x11->disp,win->self,x11->gc,vec2[i][XX]+2,vec2[i][YY]-2,
549 man->szLab[i],strlen(man->szLab[i]));
553 XSetForeground(x11->disp,x11->gc,x11->fg);