2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2013, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
47 #include "gromacs/pbcutil/pbc.h"
49 #include "gromacs/math/vec.h"
50 #include "gromacs/utility/fatalerror.h"
51 #include "gromacs/utility/smalloc.h"
61 static bool MWCallBack(t_x11 *x11, XEvent *event, Window /*w*/, void *data)
67 mw = (t_molwin *)data;
69 letter.type = ClientMessage;
70 letter.xclient.display = x11->disp;
71 letter.xclient.window = To;
72 letter.xclient.message_type = 0;
73 letter.xclient.format = 32;
77 /* Do Not draw anything, but signal parent instead, he will
80 letter.xclient.data.l[0] = IDDRAWMOL;
81 letter.xclient.data.l[1] = Button1;
82 XSendEvent(x11->disp, To, True, 0, &letter);
86 printf("Molwindow: Buttonpress\n");
88 letter.xclient.data.l[0] = IDLABEL;
89 letter.xclient.data.l[1] = (long)event->xbutton.button;
90 letter.xclient.data.l[2] = event->xbutton.x;
91 letter.xclient.data.l[3] = event->xbutton.y;
92 XSendEvent(x11->disp, To, True, 0, &letter);
95 mw->wd.width = event->xconfigure.width;
96 mw->wd.height = event->xconfigure.height;
104 void set_def (t_molwin *mw, int ePBC, matrix box)
106 mw->bShowHydrogen = true;
107 mw->bond_type = eBFat;
109 mw->boxtype = esbRect;
110 mw->realbox = TRICLINIC(box) ? esbTri : esbRect;
113 t_molwin *init_mw(t_x11 *x11, Window Parent,
114 int x, int y, int width, int height,
115 unsigned long fg, unsigned long bg,
116 int ePBC, matrix box)
121 set_def(mw, ePBC, box);
123 InitWin(&mw->wd, x, y, width, height, 1, "Mol Window");
125 mw->wd.Parent = Parent;
126 mw->wd.self = XCreateSimpleWindow(x11->disp, Parent, x, y, width, height, 1, fg, bg);
127 x11->RegisterCallback(x11, mw->wd.self, Parent, MWCallBack, mw);
128 x11->SetInputMask(x11, mw->wd.self,
129 ExposureMask | StructureNotifyMask |
134 void map_mw(t_x11 *x11, t_molwin *mw)
136 XMapWindow(x11->disp, mw->wd.self);
139 bool toggle_hydrogen(t_x11 *x11, t_molwin *mw)
141 mw->bShowHydrogen = !mw->bShowHydrogen;
142 ExposeWin(x11->disp, mw->wd.self);
144 return mw->bShowHydrogen;
147 void set_bond_type(t_x11 *x11, t_molwin *mw, int bt)
149 if (bt != mw->bond_type)
152 ExposeWin(x11->disp, mw->wd.self);
156 void set_box_type (t_x11 *x11, t_molwin *mw, int bt)
159 fprintf(stderr, "mw->boxtype = %d, bt = %d\n", mw->boxtype, bt);
161 if (bt != mw->boxtype)
163 if ((bt == esbTrunc && mw->realbox == esbTri) || bt == esbTri || bt == esbNone)
166 ExposeWin(x11->disp, mw->wd.self);
170 fprintf(stderr, "Can not change rectangular box to truncated octahedron\n");
175 void done_mw(t_x11 *x11, t_molwin *mw)
177 x11->UnRegisterCallback(x11, mw->wd.self);
181 static void draw_atom(Display *disp, Window w, GC gc,
182 atom_id ai, iv2 vec2[], unsigned long col[], int size[],
183 bool bBall, bool bPlus)
189 XSetForeground(disp, gc, col[ai]);
192 XFillCircle(disp, w, gc, xi, yi, size[ai]-1);
193 XSetForeground(disp, gc, BLACK);
194 XDrawCircle(disp, w, gc, xi, yi, size[ai]);
195 /* XSetForeground(disp,gc,WHITE);
196 XFillCircle(disp,w,gc,xi+4,yi-4,4); */
200 XDrawLine(disp, w, gc, xi-MSIZE, yi, xi+MSIZE+1, yi);
201 XDrawLine(disp, w, gc, xi, yi-MSIZE, xi, yi+MSIZE+1);
205 XDrawLine(disp, w, gc, xi-1, yi, xi+1, yi);
210 /* Global variables */
211 static rvec gl_fbox, gl_hbox, gl_mhbox;
213 static void my_init_pbc(matrix box)
217 for (i = 0; (i < DIM); i++)
219 gl_fbox[i] = box[i][i];
220 gl_hbox[i] = gl_fbox[i]*0.5;
221 gl_mhbox[i] = -gl_hbox[i];
225 static bool local_pbc_dx(rvec x1, rvec x2)
230 for (i = 0; (i < DIM); i++)
237 else if (dx <= gl_mhbox[i])
245 static void draw_bond(Display *disp, Window w, GC gc,
246 atom_id ai, atom_id aj, iv2 vec2[],
247 rvec x[], unsigned long col[], int size[], bool bBalls)
249 unsigned long ic, jc;
255 draw_atom(disp, w, gc, ai, vec2, col, size, true, false);
256 draw_atom(disp, w, gc, aj, vec2, col, size, true, false);
260 if (local_pbc_dx(x[ai], x[aj]))
274 XSetForeground(disp, gc, ic);
275 XDrawLine(disp, w, gc, xi, yi, xm, ym);
276 XSetForeground(disp, gc, jc);
277 XDrawLine(disp, w, gc, xm, ym, xj, yj);
281 XSetForeground(disp, gc, ic);
282 XDrawLine(disp, w, gc, xi, yi, xj, yj);
288 int compare_obj(const void *a, const void *b)
312 void z_fill(t_manager *man, real *zz)
317 for (i = 0, obj = man->obj; (i < man->nobj); i++, obj++)
322 obj->z = zz[obj->ai];
326 obj->z = (zz[obj->ai] + zz[obj->aj]) * 0.5;
334 int filter_vis(t_manager *man)
336 int i, nobj, nvis, nhide;
348 for (i = 0; (i < nobj); i++, obj++)
354 if (obj->eO != eOSingle)
356 bAdd = bVis[obj->aj];
361 newobj[nvis++] = *obj;
365 newobj[nhide--] = *obj;
374 void draw_objects(Display *disp, Window w, GC gc, int nobj,
375 t_object objs[], iv2 vec2[], rvec x[],
376 unsigned long col[], int size[], bool bShowHydro, int bond_type,
387 XSetLineAttributes(disp, gc, 1, LineSolid, CapNotLast, JoinRound);
390 XSetLineAttributes(disp, gc, 3, LineSolid, CapNotLast, JoinRound);
393 XSetLineAttributes(disp, gc, 5, LineSolid, CapNotLast, JoinRound);
400 gmx_fatal(FARGS, "Invalid bond_type selected: %d\n", bond_type);
403 for (i = 0; (i < nobj); i++)
409 draw_atom(disp, w, gc, obj->ai, vec2, col, size, bBalls, bPlus);
412 draw_bond(disp, w, gc, obj->ai, obj->aj, vec2, x, col, size, bBalls);
417 draw_bond(disp, w, gc, obj->ai, obj->aj, vec2, x, col, size, bBalls);
424 XSetLineAttributes(disp, gc, 1, LineSolid, CapNotLast, JoinRound);
427 static void v4_to_iv2(vec4 x4, iv2 v2, int x0, int y0, real sx, real sy)
432 v2[XX] = x0+sx*x4[XX]*inv_z;
433 v2[YY] = y0-sy*x4[YY]*inv_z;
436 static void draw_box(t_x11 *x11, Window w, t_3dview *view, matrix box,
437 int x0, int y0, real sx, real sy, int boxtype)
440 { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 },
441 { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 }
443 int tr_bonds[12][2] = {
444 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 },
445 { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 },
446 { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }
448 static int *edge = NULL;
450 rvec corner[NCUCEDGE], box_center;
454 calc_box_center(view->ecenter, box, box_center);
455 if (boxtype == esbTrunc)
457 calc_compact_unitcell_vertices(view->ecenter, box, corner);
460 edge = compact_unitcell_edges();
463 for (i = 0; (i < NCUCEDGE); i++)
465 gmx_mat4_transform_point(view->proj, corner[i], x4);
466 v4_to_iv2(x4, vec2[i], x0, y0, sx, sy);
468 XSetForeground(x11->disp, x11->gc, YELLOW);
469 for (i = 0; i < NCUCEDGE; i++)
473 XDrawLine(x11->disp, w, x11->gc,
474 vec2[i0][XX], vec2[i0][YY], vec2[i1][XX], vec2[i1][YY]);
479 if (boxtype == esbRect)
481 for (j = 0; (j < DIM); j++)
483 box_center[j] -= 0.5*box[j][j];
488 for (i = 0; (i < DIM); i++)
490 for (j = 0; (j < DIM); j++)
492 box_center[j] -= 0.5*box[i][j];
496 for (i = 0; (i < 8); i++)
498 clear_rvec(corner[i]);
499 for (j = 0; (j < DIM); j++)
501 if (boxtype == esbTri)
503 for (k = 0; (k < DIM); k++)
505 corner[i][k] += rect_tri[i][j]*box[j][k];
510 corner[i][j] = rect_tri[i][j]*box[j][j];
513 rvec_inc(corner[i], box_center);
514 gmx_mat4_transform_point(view->proj, corner[i], x4);
515 v4_to_iv2(x4, vec2[i], x0, y0, sx, sy);
519 pr_rvecs(debug, 0, "box", box, DIM);
520 pr_rvecs(debug, 0, "corner", corner, 8);
522 XSetForeground(x11->disp, x11->gc, YELLOW);
523 for (i = 0; (i < 12); i++)
527 XDrawLine(x11->disp, w, x11->gc,
528 vec2[i0][XX], vec2[i0][YY], vec2[i1][XX], vec2[i1][YY]);
533 void set_sizes(t_manager *man)
535 for (int i = 0; i < man->natom; i++)
539 man->size[i] = 180*man->vdw[i];
544 void draw_mol(t_x11 *x11, t_manager *man)
546 static char tstr[2][20];
547 static int ntime = 0;
569 sx = win->width/2*view->sc_x;
570 sy = win->height/2*view->sc_y;
572 my_init_pbc(man->box);
574 for (i = 0; (i < man->natom); i++)
578 gmx_mat4_transform_point(view->proj, man->x[i], x4);
580 v4_to_iv2(x4, vec2[i], x0, y0, sx, sy);
585 z_fill (man, man->zz);
588 XClearWindow(x11->disp, win->self);
591 sprintf(tstr[ntime], "Time: %.3f ps", man->time);
592 if (strcmp(tstr[ntime], tstr[1-ntime]) != 0)
594 set_vbtime(x11, man->vbox, tstr[ntime]);
598 if (mw->boxtype != esbNone)
600 draw_box(x11, win->self, view, man->box, x0, y0, sx, sy, mw->boxtype);
603 /* Should sort on Z-Coordinates here! */
604 nvis = filter_vis(man);
605 if (nvis && man->bSort)
607 qsort(man->obj, nvis, sizeof(man->obj[0]), compare_obj);
610 /* Draw the objects */
611 draw_objects(x11->disp, win->self, x11->gc,
612 nvis, man->obj, man->ix, man->x, man->col, man->size,
613 mw->bShowHydrogen, mw->bond_type, man->bPlus);
615 /* Draw the labels */
616 XSetForeground(x11->disp, x11->gc, WHITE);
617 for (i = 0; (i < man->natom); i++)
619 if (man->bLabel[i] && man->bVis[i])
621 XDrawString(x11->disp, win->self, x11->gc, vec2[i][XX]+2, vec2[i][YY]-2,
622 man->szLab[i], strlen(man->szLab[i]));
626 XSetForeground(x11->disp, x11->gc, x11->fg);