Valgrind suppression for OS X 10.9
[alexxy/gromacs.git] / src / gromacs / math / 3dview.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2010,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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 #include "gromacs/math/3dview.h"
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include <math.h>
44 #include "sysstuff.h"
45 #include "gromacs/utility/smalloc.h"
46 #include "macros.h"
47 #include "physics.h"
48 #include "pbc.h"
49 #include "vec.h"
50
51 #include "gmx_fatal.h"
52
53 #define N 4
54
55 void m4_op(mat4 m, rvec x, vec4 v)
56 {
57     int i;
58
59     for (i = 0; (i < N); i++)
60     {
61         v[i] = m[XX][i]*x[XX]+m[YY][i]*x[YY]+m[ZZ][i]*x[ZZ]+m[WW][i];
62     }
63 }
64
65 void unity_m4(mat4 m)
66 {
67     int i, j;
68
69     for (i = 0; (i < N); i++)
70     {
71         for (j = 0; (j < N); j++)
72         {
73             if (i == j)
74             {
75                 m[i][j] = 1.0;
76             }
77             else
78             {
79                 m[i][j] = 0.0;
80             }
81         }
82     }
83 }
84
85 void print_m4(FILE *fp, const char *s, mat4 A)
86 {
87     int i, j;
88
89     if (fp)
90     {
91         fprintf(fp, "%s: ", s);
92         for (i = 0; i < N; i++)
93         {
94             fprintf(fp, "\t");
95             for (j = 0; j < N; j++)
96             {
97                 fprintf(fp, "%10.5f", A[i][j]);
98             }
99             fprintf(fp, "\n");
100         }
101     }
102 }
103
104 void print_v4(FILE *fp, char *s, int dim, real *a)
105 {
106     int j;
107
108     if (fp)
109     {
110         fprintf(fp, "%s: ", s);
111         for (j = 0; j < dim; j++)
112         {
113             fprintf(fp, "%10.5f", a[j]);
114         }
115         fprintf(fp, "\n");
116     }
117 }
118
119 void mult_matrix(mat4 A, mat4 B, mat4 C)
120 {
121     int i, j, k;
122
123     for (i = 0; i < N; i++)
124     {
125         for (j = 0; j < N; j++)
126         {
127             A[i][j] = 0;
128             for (k = 0; (k < N); k++)
129             {
130                 A[i][j] += B[i][k]*C[k][j];
131             }
132         }
133     }
134 }
135
136 void rotate(int axis, real angle, mat4 A)
137 {
138     unity_m4(A);
139
140     switch (axis)
141     {
142         case XX:
143             A[YY][YY] =  cos(angle);
144             A[YY][ZZ] = -sin(angle);
145             A[ZZ][YY] =  sin(angle);
146             A[ZZ][ZZ] =  cos(angle);
147             break;
148         case YY:
149             A[XX][XX] =  cos(angle);
150             A[XX][ZZ] =  sin(angle);
151             A[ZZ][XX] = -sin(angle);
152             A[ZZ][ZZ] =  cos(angle);
153             break;
154         case ZZ:
155             A[XX][XX] =  cos(angle);
156             A[XX][YY] = -sin(angle);
157             A[YY][XX] =  sin(angle);
158             A[YY][YY] =  cos(angle);
159             break;
160         default:
161             gmx_fatal(FARGS, "Error: invalid axis: %d", axis);
162     }
163 }
164
165 void translate(real tx, real ty, real tz, mat4 A)
166 {
167     unity_m4(A);
168     A[3][XX] = tx;
169     A[3][YY] = ty;
170     A[3][ZZ] = tz;
171 }
172
173 static void set_scale(t_3dview *view, real sx, real sy)
174 {
175     view->sc_x = sx;
176     view->sc_y = sy;
177 }
178
179 void calculate_view(t_3dview *view)
180 {
181 #define SMALL 1e-6
182     mat4 To, Te, T1, T2, T3, T4, T5, N1, D1, D2, D3, D4, D5;
183     real dx, dy, dz, l, r;
184
185     /* eye center */
186     dx = view->eye[XX];
187     dy = view->eye[YY];
188     dz = view->eye[ZZ];
189     l  = sqrt(dx*dx+dy*dy+dz*dz);
190     r  = sqrt(dx*dx+dy*dy);
191 #ifdef DEBUG
192     print_v4(debug, "eye", N, view->eye);
193     printf("del: %10.5f%10.5f%10.5f l: %10.5f, r: %10.5f\n", dx, dy, dz, l, r);
194 #endif
195     if (l < SMALL)
196     {
197         gmx_fatal(FARGS, "Error: Zero Length Vector - No View Specified");
198     }
199     translate((real)(-view->origin[XX]),
200               (real)(-view->origin[YY]), (real)(-view->origin[ZZ]), To);
201     translate((real)(-view->eye[XX]),
202               (real)(-view->eye[YY]), (real)(-view->eye[ZZ]), Te);
203
204     unity_m4(T2);
205     T2[YY][YY] = 0, T2[YY][ZZ] = -1, T2[ZZ][YY] = 1, T2[ZZ][ZZ] = 0;
206
207     unity_m4(T3);
208     if (r > 0)
209     {
210         T3[XX][XX] = -dy/r, T3[XX][ZZ] = dx/r, T3[ZZ][XX] = -dx/r, T3[ZZ][ZZ] = -dy/r;
211     }
212
213     unity_m4(T4);
214     T4[YY][YY] = r/l, T4[YY][ZZ] = dz/l, T4[ZZ][YY] = -dz/l, T4[ZZ][ZZ] = r/l;
215
216     unity_m4(T5);
217     T5[ZZ][ZZ] = -1;
218
219     unity_m4(N1);
220     /* N1[XX][XX]=4,N1[YY][YY]=4; */
221
222     mult_matrix(T1, To, view->Rot);
223     mult_matrix(D1, Te, T2);
224     mult_matrix(D2, T3, T4);
225     mult_matrix(D3, T5, N1);
226     mult_matrix(D4, T1, D1);
227     mult_matrix(D5, D2, D3);
228
229     mult_matrix(view->proj, D4, D5);
230
231 #ifdef DEBUG
232     print_m4(debug, "T1", T1);
233     print_m4(debug, "T2", T2);
234     print_m4(debug, "T3", T3);
235     print_m4(debug, "T4", T4);
236     print_m4(debug, "T5", T5);
237     print_m4(debug, "N1", N1);
238     print_m4(debug, "Rot", view->Rot);
239     print_m4(debug, "Proj", view->proj);
240 #endif
241 }
242
243 gmx_bool zoom_3d(t_3dview *view, real fac)
244 {
245     real dr;
246     real bm, dr1, dr2;
247     int  i;
248
249     dr2 = 0;
250     for (i = 0; (i < DIM); i++)
251     {
252         dr   = view->eye[i];
253         dr2 += dr*dr;
254     }
255     dr1 = sqrt(dr2);
256     if (fac < 1)
257     {
258         bm = max(norm(view->box[XX]), max(norm(view->box[YY]), norm(view->box[ZZ])));
259         if (dr1*fac < 1.1*bm) /* Don't come to close */
260         {
261             return FALSE;
262         }
263     }
264
265     for (i = 0; (i < DIM); i++)
266     {
267         view->eye[i] *= fac;
268     }
269     calculate_view(view);
270     return TRUE;
271 }
272
273 void init_rotate_3d(t_3dview *view)
274 {
275     real rot = DEG2RAD*15;
276     int  i;
277
278     for (i = 0; (i < DIM); i++)
279     {
280         rotate(i,        rot, view->RotP[i]);
281         rotate(i, (real)(-rot), view->RotM[i]);
282 #ifdef DEBUG
283         print_m4(debug, "RotP", view->RotP[i]);
284         print_m4(debug, "RotM", view->RotM[i]);
285 #endif
286     }
287 }
288
289
290 void rotate_3d(t_3dview *view, int axis, gmx_bool bPositive)
291 {
292     int  i, j;
293     mat4 m4;
294
295     if (bPositive)
296     {
297         mult_matrix(m4, view->Rot, view->RotP[axis]);
298     }
299     else
300     {
301         mult_matrix(m4, view->Rot, view->RotM[axis]);
302     }
303     for (i = 0; (i < N); i++)
304     {
305         for (j = 0; (j < N); j++)
306         {
307             view->Rot[i][j] = m4[i][j];
308         }
309     }
310
311     calculate_view(view);
312 }
313
314 void translate_view(t_3dview *view, int axis, gmx_bool bPositive)
315 {
316 #ifdef DEBUG
317     printf("Translate called\n");
318 #endif
319     if (bPositive)
320     {
321         view->origin[axis] += view->box[axis][axis]/8;
322     }
323     else
324     {
325         view->origin[axis] -= view->box[axis][axis]/8;
326     }
327     calculate_view(view);
328 }
329
330 void reset_view(t_3dview *view)
331 {
332     int  i;
333
334 #ifdef DEBUG
335     printf("Reset view called\n");
336 #endif
337     set_scale(view, 4.0, 4.0);
338     clear_rvec(view->eye);
339     calc_box_center(view->ecenter, view->box, view->origin);
340     view->eye[ZZ] = 3.0*max(view->box[XX][XX], view->box[YY][YY]);
341     zoom_3d(view, 1.0);
342     view->eye[WW] = view->origin[WW] = 0.0;
343
344     /* Initiate the matrix */
345     unity_m4(view->Rot);
346     calculate_view(view);
347
348     init_rotate_3d(view);
349 }
350
351 t_3dview *init_view(matrix box)
352 {
353     t_3dview *view;
354     int       i, j;
355
356     snew(view, 1);
357
358     /* Copy parameters into variables */
359     for (i = 0; (i < DIM); i++)
360     {
361         for (j = 0; (j < DIM); j++)
362         {
363             view->box[i][j] = box[i][j];
364         }
365     }
366
367     view->ecenter = ecenterDEF;
368
369     reset_view(view);
370
371     return view;
372 }