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,2015,2016,2017 by the GROMACS development team.
7 * Copyright (c) 2019,2020, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
46 #include "gromacs/math/vec.h"
47 #include "gromacs/math/vecdump.h"
48 #include "gromacs/pbcutil/pbc.h"
49 #include "gromacs/utility/fatalerror.h"
50 #include "gromacs/utility/smalloc.h"
59 static bool MWCallBack(t_x11* x11, XEvent* event, Window /*w*/, void* data)
65 mw = static_cast<t_molwin*>(data);
67 letter.type = ClientMessage;
68 letter.xclient.display = x11->disp;
69 letter.xclient.window = To;
70 letter.xclient.message_type = 0;
71 letter.xclient.format = 32;
75 /* Do Not draw anything, but signal parent instead, he will
78 letter.xclient.data.l[0] = IDDRAWMOL;
79 letter.xclient.data.l[1] = Button1;
80 XSendEvent(x11->disp, To, True, 0, &letter);
84 std::printf("Molwindow: Buttonpress\n");
86 letter.xclient.data.l[0] = IDLABEL;
87 letter.xclient.data.l[1] = (long)event->xbutton.button;
88 letter.xclient.data.l[2] = event->xbutton.x;
89 letter.xclient.data.l[3] = event->xbutton.y;
90 XSendEvent(x11->disp, To, True, 0, &letter);
93 mw->wd.width = event->xconfigure.width;
94 mw->wd.height = event->xconfigure.height;
101 static void set_def(t_molwin* mw, PbcType pbcType, matrix box)
103 mw->bShowHydrogen = true;
104 mw->bond_type = eBFat;
105 mw->pbcType = pbcType;
106 mw->boxtype = esbRect;
107 mw->realbox = TRICLINIC(box) ? esbTri : esbRect;
110 t_molwin* init_mw(t_x11* x11,
124 set_def(mw, pbcType, box);
126 InitWin(&mw->wd, x, y, width, height, 1, "Mol Window");
128 mw->wd.Parent = Parent;
129 mw->wd.self = XCreateSimpleWindow(x11->disp, Parent, x, y, width, height, 1, fg, bg);
130 x11->RegisterCallback(x11, mw->wd.self, Parent, MWCallBack, mw);
131 x11->SetInputMask(x11, mw->wd.self, ExposureMask | StructureNotifyMask | ButtonPressMask);
135 void map_mw(t_x11* x11, t_molwin* mw)
137 XMapWindow(x11->disp, mw->wd.self);
140 bool toggle_hydrogen(t_x11* x11, t_molwin* mw)
142 mw->bShowHydrogen = !mw->bShowHydrogen;
143 ExposeWin(x11->disp, mw->wd.self);
145 return mw->bShowHydrogen;
148 void set_bond_type(t_x11* x11, t_molwin* mw, int bt)
150 if (bt != mw->bond_type)
153 ExposeWin(x11->disp, mw->wd.self);
157 void set_box_type(t_x11* x11, t_molwin* mw, int bt)
160 std::fprintf(stderr, "mw->boxtype = %d, bt = %d\n", mw->boxtype, bt);
162 if (bt != mw->boxtype)
164 if ((bt == esbTrunc && mw->realbox == esbTri) || bt == esbTri || bt == esbNone)
167 ExposeWin(x11->disp, mw->wd.self);
171 std::fprintf(stderr, "Can not change rectangular box to truncated octahedron\n");
176 void done_mw(t_x11* x11, t_molwin* mw)
178 x11->UnRegisterCallback(x11, mw->wd.self);
183 draw_atom(Display* disp, Window w, GC gc, int ai, iv2 vec2[], unsigned long col[], int size[], 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);
209 /* Global variables */
210 static rvec gl_fbox, gl_hbox, gl_mhbox;
212 static void my_init_pbc(matrix box)
216 for (i = 0; (i < DIM); i++)
218 gl_fbox[i] = box[i][i];
219 gl_hbox[i] = gl_fbox[i] * 0.5;
220 gl_mhbox[i] = -gl_hbox[i];
224 static bool local_pbc_dx(rvec x1, rvec x2)
229 for (i = 0; (i < DIM); i++)
236 else if (dx <= gl_mhbox[i])
245 draw_bond(Display* disp, Window w, GC gc, int ai, int aj, iv2 vec2[], rvec x[], unsigned long col[], int size[], bool bBalls)
247 unsigned long ic, jc;
253 draw_atom(disp, w, gc, ai, vec2, col, size, true, false);
254 draw_atom(disp, w, gc, aj, vec2, col, size, true, false);
258 if (local_pbc_dx(x[ai], x[aj]))
272 XSetForeground(disp, gc, ic);
273 XDrawLine(disp, w, gc, xi, yi, xm, ym);
274 XSetForeground(disp, gc, jc);
275 XDrawLine(disp, w, gc, xm, ym, xj, yj);
279 XSetForeground(disp, gc, ic);
280 XDrawLine(disp, w, gc, xi, yi, xj, yj);
286 int compare_obj(const void* a, const void* b)
288 const t_object *oa, *ob;
291 oa = static_cast<const t_object*>(a);
292 ob = static_cast<const t_object*>(b);
310 void z_fill(t_manager* man, real* zz)
315 for (i = 0, obj = man->obj; (i < man->nobj); i++, obj++)
319 case eOSingle: obj->z = zz[obj->ai]; break;
321 case eOHBond: obj->z = (zz[obj->ai] + zz[obj->aj]) * 0.5; break;
327 int filter_vis(t_manager* man)
329 int i, nobj, nvis, nhide;
341 for (i = 0; (i < nobj); i++, obj++)
347 if (obj->eO != eOSingle)
349 bAdd = bVis[obj->aj];
354 newobj[nvis++] = *obj;
358 newobj[nhide--] = *obj;
367 static void draw_objects(Display* disp,
387 case eBThin: XSetLineAttributes(disp, gc, 1, LineSolid, CapNotLast, JoinRound); break;
388 case eBFat: XSetLineAttributes(disp, gc, 3, LineSolid, CapNotLast, JoinRound); break;
389 case eBVeryFat: XSetLineAttributes(disp, gc, 5, LineSolid, CapNotLast, JoinRound); break;
394 default: gmx_fatal(FARGS, "Invalid bond_type selected: %d\n", bond_type); break;
396 for (i = 0; (i < nobj); i++)
401 case eOSingle: draw_atom(disp, w, gc, obj->ai, vec2, col, size, bBalls, bPlus); break;
403 draw_bond(disp, w, gc, obj->ai, obj->aj, vec2, x, col, size, bBalls);
408 draw_bond(disp, w, gc, obj->ai, obj->aj, vec2, x, col, size, bBalls);
414 XSetLineAttributes(disp, gc, 1, LineSolid, CapNotLast, JoinRound);
417 static void v4_to_iv2(vec4 x4, iv2 v2, int x0, int y0, real sx, real sy)
421 inv_z = 1.0 / x4[ZZ];
422 v2[XX] = x0 + sx * x4[XX] * inv_z;
423 v2[YY] = y0 - sy * x4[YY] * inv_z;
426 static void draw_box(t_x11* x11, Window w, t_3dview* view, matrix box, int x0, int y0, real sx, real sy, int boxtype)
428 rvec rect_tri[8] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 },
429 { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 } };
430 int tr_bonds[12][2] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 },
431 { 6, 7 }, { 7, 4 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } };
432 static int* edge = nullptr;
434 rvec corner[NCUCEDGE], box_center;
438 calc_box_center(view->ecenter, box, box_center);
439 if (boxtype == esbTrunc)
441 calc_compact_unitcell_vertices(view->ecenter, box, corner);
444 edge = compact_unitcell_edges();
447 for (i = 0; (i < NCUCEDGE); i++)
449 gmx_mat4_transform_point(view->proj, corner[i], x4);
450 v4_to_iv2(x4, vec2[i], x0, y0, sx, sy);
452 XSetForeground(x11->disp, x11->gc, YELLOW);
453 for (i = 0; i < NCUCEDGE; i++)
456 i1 = edge[2 * i + 1];
457 XDrawLine(x11->disp, w, x11->gc, vec2[i0][XX], vec2[i0][YY], vec2[i1][XX], vec2[i1][YY]);
462 if (boxtype == esbRect)
464 for (j = 0; (j < DIM); j++)
466 box_center[j] -= 0.5 * box[j][j];
471 for (i = 0; (i < DIM); i++)
473 for (j = 0; (j < DIM); j++)
475 box_center[j] -= 0.5 * box[i][j];
479 for (i = 0; (i < 8); i++)
481 clear_rvec(corner[i]);
482 for (j = 0; (j < DIM); j++)
484 if (boxtype == esbTri)
486 for (k = 0; (k < DIM); k++)
488 corner[i][k] += rect_tri[i][j] * box[j][k];
493 corner[i][j] = rect_tri[i][j] * box[j][j];
496 rvec_inc(corner[i], box_center);
497 gmx_mat4_transform_point(view->proj, corner[i], x4);
498 v4_to_iv2(x4, vec2[i], x0, y0, sx, sy);
502 pr_rvecs(debug, 0, "box", box, DIM);
503 pr_rvecs(debug, 0, "corner", corner, 8);
505 XSetForeground(x11->disp, x11->gc, YELLOW);
506 for (i = 0; (i < 12); i++)
510 XDrawLine(x11->disp, w, x11->gc, vec2[i0][XX], vec2[i0][YY], vec2[i1][XX], vec2[i1][YY]);
515 void set_sizes(t_manager* man)
517 for (int i = 0; i < man->natom; i++)
521 man->size[i] = 180 * man->vdw[i];
526 void draw_mol(t_x11* x11, t_manager* man)
528 static char tstr[2][20];
529 static int ntime = 0;
550 y0 = win->height / 2;
551 sx = win->width / 2 * view->sc_x;
552 sy = win->height / 2 * view->sc_y;
554 my_init_pbc(man->box);
556 for (i = 0; (i < man->natom); i++)
560 gmx_mat4_transform_point(view->proj, man->x[i], x4);
562 v4_to_iv2(x4, vec2[i], x0, y0, sx, sy);
567 z_fill(man, man->zz);
570 XClearWindow(x11->disp, win->self);
573 std::sprintf(tstr[ntime], "Time: %.3f ps", man->time);
574 if (std::strcmp(tstr[ntime], tstr[1 - ntime]) != 0)
576 set_vbtime(x11, man->vbox, tstr[ntime]);
580 if (mw->boxtype != esbNone)
582 draw_box(x11, win->self, view, man->box, x0, y0, sx, sy, mw->boxtype);
585 /* Should sort on Z-Coordinates here! */
586 nvis = filter_vis(man);
587 if (nvis && man->bSort)
589 std::qsort(man->obj, nvis, sizeof(man->obj[0]), compare_obj);
592 /* Draw the objects */
593 draw_objects(x11->disp,
606 /* Draw the labels */
607 XSetForeground(x11->disp, x11->gc, WHITE);
608 for (i = 0; (i < man->natom); i++)
610 if (man->bLabel[i] && man->bVis[i])
612 XDrawString(x11->disp,
618 std::strlen(man->szLab[i]));
622 XSetForeground(x11->disp, x11->gc, x11->fg);