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, 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.
45 #include "gromacs/math/vec.h"
46 #include "gromacs/math/vecdump.h"
47 #include "gromacs/pbcutil/pbc.h"
48 #include "gromacs/utility/fatalerror.h"
49 #include "gromacs/utility/smalloc.h"
58 static bool MWCallBack(t_x11
*x11
, XEvent
*event
, Window
/*w*/, void *data
)
64 mw
= static_cast<t_molwin
*>(data
);
66 letter
.type
= ClientMessage
;
67 letter
.xclient
.display
= x11
->disp
;
68 letter
.xclient
.window
= To
;
69 letter
.xclient
.message_type
= 0;
70 letter
.xclient
.format
= 32;
74 /* Do Not draw anything, but signal parent instead, he will
77 letter
.xclient
.data
.l
[0] = IDDRAWMOL
;
78 letter
.xclient
.data
.l
[1] = Button1
;
79 XSendEvent(x11
->disp
, To
, True
, 0, &letter
);
83 std::printf("Molwindow: Buttonpress\n");
85 letter
.xclient
.data
.l
[0] = IDLABEL
;
86 letter
.xclient
.data
.l
[1] = (long)event
->xbutton
.button
;
87 letter
.xclient
.data
.l
[2] = event
->xbutton
.x
;
88 letter
.xclient
.data
.l
[3] = event
->xbutton
.y
;
89 XSendEvent(x11
->disp
, To
, True
, 0, &letter
);
92 mw
->wd
.width
= event
->xconfigure
.width
;
93 mw
->wd
.height
= event
->xconfigure
.height
;
101 static void set_def (t_molwin
*mw
, int ePBC
, matrix box
)
103 mw
->bShowHydrogen
= true;
104 mw
->bond_type
= eBFat
;
106 mw
->boxtype
= esbRect
;
107 mw
->realbox
= TRICLINIC(box
) ? esbTri
: esbRect
;
110 t_molwin
*init_mw(t_x11
*x11
, Window Parent
,
111 int x
, int y
, int width
, int height
,
112 unsigned long fg
, unsigned long bg
,
113 int ePBC
, matrix box
)
118 set_def(mw
, ePBC
, box
);
120 InitWin(&mw
->wd
, x
, y
, width
, height
, 1, "Mol Window");
122 mw
->wd
.Parent
= Parent
;
123 mw
->wd
.self
= XCreateSimpleWindow(x11
->disp
, Parent
, x
, y
, width
, height
, 1, fg
, bg
);
124 x11
->RegisterCallback(x11
, mw
->wd
.self
, Parent
, MWCallBack
, mw
);
125 x11
->SetInputMask(x11
, mw
->wd
.self
,
126 ExposureMask
| StructureNotifyMask
|
131 void map_mw(t_x11
*x11
, t_molwin
*mw
)
133 XMapWindow(x11
->disp
, mw
->wd
.self
);
136 bool toggle_hydrogen(t_x11
*x11
, t_molwin
*mw
)
138 mw
->bShowHydrogen
= !mw
->bShowHydrogen
;
139 ExposeWin(x11
->disp
, mw
->wd
.self
);
141 return mw
->bShowHydrogen
;
144 void set_bond_type(t_x11
*x11
, t_molwin
*mw
, int bt
)
146 if (bt
!= mw
->bond_type
)
149 ExposeWin(x11
->disp
, mw
->wd
.self
);
153 void set_box_type (t_x11
*x11
, t_molwin
*mw
, int bt
)
156 std::fprintf(stderr
, "mw->boxtype = %d, bt = %d\n", mw
->boxtype
, bt
);
158 if (bt
!= mw
->boxtype
)
160 if ((bt
== esbTrunc
&& mw
->realbox
== esbTri
) || bt
== esbTri
|| bt
== esbNone
)
163 ExposeWin(x11
->disp
, mw
->wd
.self
);
167 std::fprintf(stderr
, "Can not change rectangular box to truncated octahedron\n");
172 void done_mw(t_x11
*x11
, t_molwin
*mw
)
174 x11
->UnRegisterCallback(x11
, mw
->wd
.self
);
178 static void draw_atom(Display
*disp
, Window w
, GC gc
,
179 int ai
, iv2 vec2
[], unsigned long col
[], int size
[],
180 bool bBall
, bool bPlus
)
186 XSetForeground(disp
, gc
, col
[ai
]);
189 XFillCircle(disp
, w
, gc
, xi
, yi
, size
[ai
]-1);
190 XSetForeground(disp
, gc
, BLACK
);
191 XDrawCircle(disp
, w
, gc
, xi
, yi
, size
[ai
]);
192 /* XSetForeground(disp,gc,WHITE);
193 XFillCircle(disp,w,gc,xi+4,yi-4,4); */
197 XDrawLine(disp
, w
, gc
, xi
-MSIZE
, yi
, xi
+MSIZE
+1, yi
);
198 XDrawLine(disp
, w
, gc
, xi
, yi
-MSIZE
, xi
, yi
+MSIZE
+1);
202 XDrawLine(disp
, w
, gc
, xi
-1, yi
, xi
+1, yi
);
207 /* Global variables */
208 static rvec gl_fbox
, gl_hbox
, gl_mhbox
;
210 static void my_init_pbc(matrix box
)
214 for (i
= 0; (i
< DIM
); i
++)
216 gl_fbox
[i
] = box
[i
][i
];
217 gl_hbox
[i
] = gl_fbox
[i
]*0.5;
218 gl_mhbox
[i
] = -gl_hbox
[i
];
222 static bool local_pbc_dx(rvec x1
, rvec x2
)
227 for (i
= 0; (i
< DIM
); i
++)
234 else if (dx
<= gl_mhbox
[i
])
242 static void draw_bond(Display
*disp
, Window w
, GC gc
,
243 int ai
, int aj
, iv2 vec2
[],
244 rvec x
[], unsigned long col
[], int size
[], bool bBalls
)
246 unsigned long ic
, jc
;
252 draw_atom(disp
, w
, gc
, ai
, vec2
, col
, size
, true, false);
253 draw_atom(disp
, w
, gc
, aj
, vec2
, col
, size
, true, false);
257 if (local_pbc_dx(x
[ai
], x
[aj
]))
271 XSetForeground(disp
, gc
, ic
);
272 XDrawLine(disp
, w
, gc
, xi
, yi
, xm
, ym
);
273 XSetForeground(disp
, gc
, jc
);
274 XDrawLine(disp
, w
, gc
, xm
, ym
, xj
, yj
);
278 XSetForeground(disp
, gc
, ic
);
279 XDrawLine(disp
, w
, gc
, xi
, yi
, xj
, yj
);
285 int compare_obj(const void *a
, const void *b
)
287 const t_object
*oa
, *ob
;
290 oa
= static_cast<const t_object
*>(a
);
291 ob
= static_cast<const t_object
*>(b
);
309 void z_fill(t_manager
*man
, real
*zz
)
314 for (i
= 0, obj
= man
->obj
; (i
< man
->nobj
); i
++, obj
++)
319 obj
->z
= zz
[obj
->ai
];
323 obj
->z
= (zz
[obj
->ai
] + zz
[obj
->aj
]) * 0.5;
331 int filter_vis(t_manager
*man
)
333 int i
, nobj
, nvis
, nhide
;
345 for (i
= 0; (i
< nobj
); i
++, obj
++)
351 if (obj
->eO
!= eOSingle
)
353 bAdd
= bVis
[obj
->aj
];
358 newobj
[nvis
++] = *obj
;
362 newobj
[nhide
--] = *obj
;
371 static void draw_objects(Display
*disp
, Window w
, GC gc
, int nobj
,
372 t_object objs
[], iv2 vec2
[], rvec x
[],
373 unsigned long col
[], int size
[], bool bShowHydro
, int bond_type
,
384 XSetLineAttributes(disp
, gc
, 1, LineSolid
, CapNotLast
, JoinRound
);
387 XSetLineAttributes(disp
, gc
, 3, LineSolid
, CapNotLast
, JoinRound
);
390 XSetLineAttributes(disp
, gc
, 5, LineSolid
, CapNotLast
, JoinRound
);
397 gmx_fatal(FARGS
, "Invalid bond_type selected: %d\n", bond_type
);
400 for (i
= 0; (i
< nobj
); i
++)
406 draw_atom(disp
, w
, gc
, obj
->ai
, vec2
, col
, size
, bBalls
, bPlus
);
409 draw_bond(disp
, w
, gc
, obj
->ai
, obj
->aj
, vec2
, x
, col
, size
, bBalls
);
414 draw_bond(disp
, w
, gc
, obj
->ai
, obj
->aj
, vec2
, x
, col
, size
, bBalls
);
421 XSetLineAttributes(disp
, gc
, 1, LineSolid
, CapNotLast
, JoinRound
);
424 static void v4_to_iv2(vec4 x4
, iv2 v2
, int x0
, int y0
, real sx
, real sy
)
429 v2
[XX
] = x0
+sx
*x4
[XX
]*inv_z
;
430 v2
[YY
] = y0
-sy
*x4
[YY
]*inv_z
;
433 static void draw_box(t_x11
*x11
, Window w
, t_3dview
*view
, matrix box
,
434 int x0
, int y0
, real sx
, real sy
, int boxtype
)
437 { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 },
438 { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 }
440 int tr_bonds
[12][2] = {
441 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 },
442 { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 },
443 { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }
445 static int *edge
= nullptr;
447 rvec corner
[NCUCEDGE
], box_center
;
451 calc_box_center(view
->ecenter
, box
, box_center
);
452 if (boxtype
== esbTrunc
)
454 calc_compact_unitcell_vertices(view
->ecenter
, box
, corner
);
457 edge
= compact_unitcell_edges();
460 for (i
= 0; (i
< NCUCEDGE
); i
++)
462 gmx_mat4_transform_point(view
->proj
, corner
[i
], x4
);
463 v4_to_iv2(x4
, vec2
[i
], x0
, y0
, sx
, sy
);
465 XSetForeground(x11
->disp
, x11
->gc
, YELLOW
);
466 for (i
= 0; i
< NCUCEDGE
; i
++)
470 XDrawLine(x11
->disp
, w
, x11
->gc
,
471 vec2
[i0
][XX
], vec2
[i0
][YY
], vec2
[i1
][XX
], vec2
[i1
][YY
]);
476 if (boxtype
== esbRect
)
478 for (j
= 0; (j
< DIM
); j
++)
480 box_center
[j
] -= 0.5*box
[j
][j
];
485 for (i
= 0; (i
< DIM
); i
++)
487 for (j
= 0; (j
< DIM
); j
++)
489 box_center
[j
] -= 0.5*box
[i
][j
];
493 for (i
= 0; (i
< 8); i
++)
495 clear_rvec(corner
[i
]);
496 for (j
= 0; (j
< DIM
); j
++)
498 if (boxtype
== esbTri
)
500 for (k
= 0; (k
< DIM
); k
++)
502 corner
[i
][k
] += rect_tri
[i
][j
]*box
[j
][k
];
507 corner
[i
][j
] = rect_tri
[i
][j
]*box
[j
][j
];
510 rvec_inc(corner
[i
], box_center
);
511 gmx_mat4_transform_point(view
->proj
, corner
[i
], x4
);
512 v4_to_iv2(x4
, vec2
[i
], x0
, y0
, sx
, sy
);
516 pr_rvecs(debug
, 0, "box", box
, DIM
);
517 pr_rvecs(debug
, 0, "corner", corner
, 8);
519 XSetForeground(x11
->disp
, x11
->gc
, YELLOW
);
520 for (i
= 0; (i
< 12); i
++)
524 XDrawLine(x11
->disp
, w
, x11
->gc
,
525 vec2
[i0
][XX
], vec2
[i0
][YY
], vec2
[i1
][XX
], vec2
[i1
][YY
]);
530 void set_sizes(t_manager
*man
)
532 for (int i
= 0; i
< man
->natom
; i
++)
536 man
->size
[i
] = 180*man
->vdw
[i
];
541 void draw_mol(t_x11
*x11
, t_manager
*man
)
543 static char tstr
[2][20];
544 static int ntime
= 0;
566 sx
= win
->width
/2*view
->sc_x
;
567 sy
= win
->height
/2*view
->sc_y
;
569 my_init_pbc(man
->box
);
571 for (i
= 0; (i
< man
->natom
); i
++)
575 gmx_mat4_transform_point(view
->proj
, man
->x
[i
], x4
);
577 v4_to_iv2(x4
, vec2
[i
], x0
, y0
, sx
, sy
);
582 z_fill (man
, man
->zz
);
585 XClearWindow(x11
->disp
, win
->self
);
588 std::sprintf(tstr
[ntime
], "Time: %.3f ps", man
->time
);
589 if (std::strcmp(tstr
[ntime
], tstr
[1-ntime
]) != 0)
591 set_vbtime(x11
, man
->vbox
, tstr
[ntime
]);
595 if (mw
->boxtype
!= esbNone
)
597 draw_box(x11
, win
->self
, view
, man
->box
, x0
, y0
, sx
, sy
, mw
->boxtype
);
600 /* Should sort on Z-Coordinates here! */
601 nvis
= filter_vis(man
);
602 if (nvis
&& man
->bSort
)
604 std::qsort(man
->obj
, nvis
, sizeof(man
->obj
[0]), compare_obj
);
607 /* Draw the objects */
608 draw_objects(x11
->disp
, win
->self
, x11
->gc
,
609 nvis
, man
->obj
, man
->ix
, man
->x
, man
->col
, man
->size
,
610 mw
->bShowHydrogen
, mw
->bond_type
, man
->bPlus
);
612 /* Draw the labels */
613 XSetForeground(x11
->disp
, x11
->gc
, WHITE
);
614 for (i
= 0; (i
< man
->natom
); i
++)
616 if (man
->bLabel
[i
] && man
->bVis
[i
])
618 XDrawString(x11
->disp
, win
->self
, x11
->gc
, vec2
[i
][XX
]+2, vec2
[i
][YY
]-2,
619 man
->szLab
[i
], std::strlen(man
->szLab
[i
]));
623 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);