ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/SHAPES/MatVec3.c
Revision: 1271
Committed: Tue Jun 15 20:20:36 2004 UTC (20 years ago) by gezelter
Content type: text/plain
File size: 12568 byte(s)
Log Message:
Major changes for rigidbodies

File Contents

# User Rev Content
1 gezelter 1271 #include <stdio.h>
2     #include <math.h>
3     #include <stdlib.h>
4     #include "MatVec3.h"
5    
6     /*
7     * Contains various utilities for dealing with 3x3 matrices and
8     * length 3 vectors
9     */
10    
11     void identityMat3(double A[3][3]) {
12     int i;
13     for (i = 0; i < 3; i++) {
14     A[i][0] = A[i][1] = A[i][2] = 0.0;
15     A[i][i] = 1.0;
16     }
17     }
18    
19     void swapVectors3(double v1[3], double v2[3]) {
20     int i;
21     for (i = 0; i < 3; i++) {
22     double tmp = v1[i];
23     v1[i] = v2[i];
24     v2[i] = tmp;
25     }
26     }
27    
28     double normalize3(double x[3]) {
29     double den;
30     int i;
31     if ( (den = norm3(x)) != 0.0 ) {
32     for (i=0; i < 3; i++)
33     {
34     x[i] /= den;
35     }
36     }
37     return den;
38     }
39    
40     void matMul3(double a[3][3], double b[3][3], double c[3][3]) {
41     double r00, r01, r02, r10, r11, r12, r20, r21, r22;
42    
43     r00 = a[0][0]*b[0][0] + a[0][1]*b[1][0] + a[0][2]*b[2][0];
44     r01 = a[0][0]*b[0][1] + a[0][1]*b[1][1] + a[0][2]*b[2][1];
45     r02 = a[0][0]*b[0][2] + a[0][1]*b[1][2] + a[0][2]*b[2][2];
46    
47     r10 = a[1][0]*b[0][0] + a[1][1]*b[1][0] + a[1][2]*b[2][0];
48     r11 = a[1][0]*b[0][1] + a[1][1]*b[1][1] + a[1][2]*b[2][1];
49     r12 = a[1][0]*b[0][2] + a[1][1]*b[1][2] + a[1][2]*b[2][2];
50    
51     r20 = a[2][0]*b[0][0] + a[2][1]*b[1][0] + a[2][2]*b[2][0];
52     r21 = a[2][0]*b[0][1] + a[2][1]*b[1][1] + a[2][2]*b[2][1];
53     r22 = a[2][0]*b[0][2] + a[2][1]*b[1][2] + a[2][2]*b[2][2];
54    
55     c[0][0] = r00; c[0][1] = r01; c[0][2] = r02;
56     c[1][0] = r10; c[1][1] = r11; c[1][2] = r12;
57     c[2][0] = r20; c[2][1] = r21; c[2][2] = r22;
58     }
59    
60     void matVecMul3(double m[3][3], double inVec[3], double outVec[3]) {
61     double a0, a1, a2;
62    
63     a0 = inVec[0]; a1 = inVec[1]; a2 = inVec[2];
64    
65     outVec[0] = m[0][0]*a0 + m[0][1]*a1 + m[0][2]*a2;
66     outVec[1] = m[1][0]*a0 + m[1][1]*a1 + m[1][2]*a2;
67     outVec[2] = m[2][0]*a0 + m[2][1]*a1 + m[2][2]*a2;
68     }
69    
70     double matDet3(double a[3][3]) {
71     int i, j, k;
72     double determinant;
73    
74     determinant = 0.0;
75    
76     for(i = 0; i < 3; i++) {
77     j = (i+1)%3;
78     k = (i+2)%3;
79    
80     determinant += a[0][i] * (a[1][j]*a[2][k] - a[1][k]*a[2][j]);
81     }
82    
83     return determinant;
84     }
85    
86     void invertMat3(double a[3][3], double b[3][3]) {
87    
88     int i, j, k, l, m, n;
89     double determinant;
90    
91     determinant = matDet3( a );
92    
93     if (determinant == 0.0) {
94     printf(
95     "Can't invert a matrix with a zero determinant!\n");
96     exit(-1);
97     }
98    
99     for (i=0; i < 3; i++) {
100     j = (i+1)%3;
101     k = (i+2)%3;
102     for(l = 0; l < 3; l++) {
103     m = (l+1)%3;
104     n = (l+2)%3;
105    
106     b[l][i] = (a[j][m]*a[k][n] - a[j][n]*a[k][m]) / determinant;
107     }
108     }
109     }
110    
111     void transposeMat3(double in[3][3], double out[3][3]) {
112     double temp[3][3];
113     int i, j;
114    
115     for (i = 0; i < 3; i++) {
116     for (j = 0; j < 3; j++) {
117     temp[j][i] = in[i][j];
118     }
119     }
120     for (i = 0; i < 3; i++) {
121     for (j = 0; j < 3; j++) {
122     out[i][j] = temp[i][j];
123     }
124     }
125     }
126    
127     void printMat3(double A[3][3] ){
128    
129     fprintf(stderr, "[ %g, %g, %g ]\n[ %g, %g, %g ]\n[ %g, %g, %g ]\n",
130     A[0][0] , A[0][1] , A[0][2],
131     A[1][0] , A[1][1] , A[1][2],
132     A[2][0] , A[2][1] , A[2][2]) ;
133     }
134    
135     void printMat9(double A[9] ){
136    
137     fprintf(stderr, "[ %g, %g, %g ]\n[ %g, %g, %g ]\n[ %g, %g, %g ]\n",
138     A[0], A[1], A[2],
139     A[3], A[4], A[5],
140     A[6], A[7], A[8]);
141     }
142    
143     double matTrace3(double m[3][3]){
144     double trace;
145     trace = m[0][0] + m[1][1] + m[2][2];
146    
147     return trace;
148     }
149    
150     void crossProduct3(double a[3],double b[3], double out[3]){
151    
152     out[0] = a[1] * b[2] - a[2] * b[1];
153     out[1] = a[2] * b[0] - a[0] * b[2] ;
154     out[2] = a[0] * b[1] - a[1] * b[0];
155    
156     }
157    
158     double dotProduct3(double a[3], double b[3]){
159     return a[0]*b[0] + a[1]*b[1]+ a[2]*b[2];
160     }
161    
162     //----------------------------------------------------------------------------
163     // Extract the eigenvalues and eigenvectors from a 3x3 matrix.
164     // The eigenvectors (the columns of V) will be normalized.
165     // The eigenvectors are aligned optimally with the x, y, and z
166     // axes respectively.
167    
168     void diagonalize3x3(const double A[3][3], double w[3], double V[3][3]) {
169     int i,j,k,maxI;
170     double tmp, maxVal;
171    
172     // do the matrix[3][3] to **matrix conversion for Jacobi
173     double C[3][3];
174     double *ATemp[3],*VTemp[3];
175     for (i = 0; i < 3; i++)
176     {
177     C[i][0] = A[i][0];
178     C[i][1] = A[i][1];
179     C[i][2] = A[i][2];
180     ATemp[i] = C[i];
181     VTemp[i] = V[i];
182     }
183    
184     // diagonalize using Jacobi
185     JacobiN(ATemp,3,w,VTemp);
186    
187     // if all the eigenvalues are the same, return identity matrix
188     if (w[0] == w[1] && w[0] == w[2])
189     {
190     identityMat3(V);
191     return;
192     }
193    
194     // transpose temporarily, it makes it easier to sort the eigenvectors
195     transposeMat3(V,V);
196    
197     // if two eigenvalues are the same, re-orthogonalize to optimally line
198     // up the eigenvectors with the x, y, and z axes
199     for (i = 0; i < 3; i++)
200     {
201     if (w[(i+1)%3] == w[(i+2)%3]) // two eigenvalues are the same
202     {
203     // find maximum element of the independant eigenvector
204     maxVal = fabs(V[i][0]);
205     maxI = 0;
206     for (j = 1; j < 3; j++)
207     {
208     if (maxVal < (tmp = fabs(V[i][j])))
209     {
210     maxVal = tmp;
211     maxI = j;
212     }
213     }
214     // swap the eigenvector into its proper position
215     if (maxI != i)
216     {
217     tmp = w[maxI];
218     w[maxI] = w[i];
219     w[i] = tmp;
220     swapVectors3(V[i],V[maxI]);
221     }
222     // maximum element of eigenvector should be positive
223     if (V[maxI][maxI] < 0)
224     {
225     V[maxI][0] = -V[maxI][0];
226     V[maxI][1] = -V[maxI][1];
227     V[maxI][2] = -V[maxI][2];
228     }
229    
230     // re-orthogonalize the other two eigenvectors
231     j = (maxI+1)%3;
232     k = (maxI+2)%3;
233    
234     V[j][0] = 0.0;
235     V[j][1] = 0.0;
236     V[j][2] = 0.0;
237     V[j][j] = 1.0;
238     crossProduct3(V[maxI],V[j],V[k]);
239     normalize3(V[k]);
240     crossProduct3(V[k],V[maxI],V[j]);
241    
242     // transpose vectors back to columns
243     transposeMat3(V,V);
244     return;
245     }
246     }
247    
248     // the three eigenvalues are different, just sort the eigenvectors
249     // to align them with the x, y, and z axes
250    
251     // find the vector with the largest x element, make that vector
252     // the first vector
253     maxVal = fabs(V[0][0]);
254     maxI = 0;
255     for (i = 1; i < 3; i++)
256     {
257     if (maxVal < (tmp = fabs(V[i][0])))
258     {
259     maxVal = tmp;
260     maxI = i;
261     }
262     }
263     // swap eigenvalue and eigenvector
264     if (maxI != 0)
265     {
266     tmp = w[maxI];
267     w[maxI] = w[0];
268     w[0] = tmp;
269     swapVectors3(V[maxI],V[0]);
270     }
271     // do the same for the y element
272     if (fabs(V[1][1]) < fabs(V[2][1]))
273     {
274     tmp = w[2];
275     w[2] = w[1];
276     w[1] = tmp;
277     swapVectors3(V[2],V[1]);
278     }
279    
280     // ensure that the sign of the eigenvectors is correct
281     for (i = 0; i < 2; i++)
282     {
283     if (V[i][i] < 0)
284     {
285     V[i][0] = -V[i][0];
286     V[i][1] = -V[i][1];
287     V[i][2] = -V[i][2];
288     }
289     }
290     // set sign of final eigenvector to ensure that determinant is positive
291     if (matDet3(V) < 0)
292     {
293     V[2][0] = -V[2][0];
294     V[2][1] = -V[2][1];
295     V[2][2] = -V[2][2];
296     }
297    
298     // transpose the eigenvectors back again
299     transposeMat3(V,V);
300     }
301    
302    
303     #define MAT_ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau); a[k][l]=h+s*(g-h*tau);
304    
305     #define MAX_ROTATIONS 20
306    
307     // Jacobi iteration for the solution of eigenvectors/eigenvalues of a nxn
308     // real symmetric matrix. Square nxn matrix a; size of matrix in n;
309     // output eigenvalues in w; and output eigenvectors in v. Resulting
310     // eigenvalues/vectors are sorted in decreasing order; eigenvectors are
311     // normalized.
312     int JacobiN(double **a, int n, double *w, double **v) {
313    
314     int i, j, k, iq, ip, numPos;
315     double tresh, theta, tau, t, sm, s, h, g, c, tmp;
316     double bspace[4], zspace[4];
317     double *b = bspace;
318     double *z = zspace;
319    
320     // only allocate memory if the matrix is large
321     if (n > 4)
322     {
323     b = (double *) calloc(n, sizeof(double));
324     z = (double *) calloc(n, sizeof(double));
325     }
326    
327     // initialize
328     for (ip=0; ip<n; ip++)
329     {
330     for (iq=0; iq<n; iq++)
331     {
332     v[ip][iq] = 0.0;
333     }
334     v[ip][ip] = 1.0;
335     }
336     for (ip=0; ip<n; ip++)
337     {
338     b[ip] = w[ip] = a[ip][ip];
339     z[ip] = 0.0;
340     }
341    
342     // begin rotation sequence
343     for (i=0; i<MAX_ROTATIONS; i++)
344     {
345     sm = 0.0;
346     for (ip=0; ip<n-1; ip++)
347     {
348     for (iq=ip+1; iq<n; iq++)
349     {
350     sm += fabs(a[ip][iq]);
351     }
352     }
353     if (sm == 0.0)
354     {
355     break;
356     }
357    
358     if (i < 3) // first 3 sweeps
359     {
360     tresh = 0.2*sm/(n*n);
361     }
362     else
363     {
364     tresh = 0.0;
365     }
366    
367     for (ip=0; ip<n-1; ip++)
368     {
369     for (iq=ip+1; iq<n; iq++)
370     {
371     g = 100.0*fabs(a[ip][iq]);
372    
373     // after 4 sweeps
374     if (i > 3 && (fabs(w[ip])+g) == fabs(w[ip])
375     && (fabs(w[iq])+g) == fabs(w[iq]))
376     {
377     a[ip][iq] = 0.0;
378     }
379     else if (fabs(a[ip][iq]) > tresh)
380     {
381     h = w[iq] - w[ip];
382     if ( (fabs(h)+g) == fabs(h))
383     {
384     t = (a[ip][iq]) / h;
385     }
386     else
387     {
388     theta = 0.5*h / (a[ip][iq]);
389     t = 1.0 / (fabs(theta)+sqrt(1.0+theta*theta));
390     if (theta < 0.0)
391     {
392     t = -t;
393     }
394     }
395     c = 1.0 / sqrt(1+t*t);
396     s = t*c;
397     tau = s/(1.0+c);
398     h = t*a[ip][iq];
399     z[ip] -= h;
400     z[iq] += h;
401     w[ip] -= h;
402     w[iq] += h;
403     a[ip][iq]=0.0;
404    
405     // ip already shifted left by 1 unit
406     for (j = 0;j <= ip-1;j++)
407     {
408     MAT_ROTATE(a,j,ip,j,iq)
409     }
410     // ip and iq already shifted left by 1 unit
411     for (j = ip+1;j <= iq-1;j++)
412     {
413     MAT_ROTATE(a,ip,j,j,iq)
414     }
415     // iq already shifted left by 1 unit
416     for (j=iq+1; j<n; j++)
417     {
418     MAT_ROTATE(a,ip,j,iq,j)
419     }
420     for (j=0; j<n; j++)
421     {
422     MAT_ROTATE(v,j,ip,j,iq)
423     }
424     }
425     }
426     }
427    
428     for (ip=0; ip<n; ip++)
429     {
430     b[ip] += z[ip];
431     w[ip] = b[ip];
432     z[ip] = 0.0;
433     }
434     }
435    
436     //// this is NEVER called
437     if ( i >= MAX_ROTATIONS )
438     {
439     printf( "Jacobi: Error extracting eigenfunctions!\n");
440     exit(-1);
441     }
442    
443     // sort eigenfunctions these changes do not affect accuracy
444     for (j=0; j<n-1; j++) // boundary incorrect
445     {
446     k = j;
447     tmp = w[k];
448     for (i=j+1; i<n; i++) // boundary incorrect, shifted already
449     {
450     if (w[i] >= tmp) // why exchage if same?
451     {
452     k = i;
453     tmp = w[k];
454     }
455     }
456     if (k != j)
457     {
458     w[k] = w[j];
459     w[j] = tmp;
460     for (i=0; i<n; i++)
461     {
462     tmp = v[i][j];
463     v[i][j] = v[i][k];
464     v[i][k] = tmp;
465     }
466     }
467     }
468     // insure eigenvector consistency (i.e., Jacobi can compute vectors that
469     // are negative of one another (.707,.707,0) and (-.707,-.707,0). This can
470     // reek havoc in hyperstreamline/other stuff. We will select the most
471     // positive eigenvector.
472     int ceil_half_n = (n >> 1) + (n & 1);
473     for (j=0; j<n; j++)
474     {
475     for (numPos=0, i=0; i<n; i++)
476     {
477     if ( v[i][j] >= 0.0 )
478     {
479     numPos++;
480     }
481     }
482     // if ( numPos < ceil(double(n)/double(2.0)) )
483     if ( numPos < ceil_half_n)
484     {
485     for(i=0; i<n; i++)
486     {
487     v[i][j] *= -1.0;
488     }
489     }
490     }
491    
492     if (n > 4)
493     {
494     free(b);
495     free(z);
496     }
497     return 1;
498     }
499    
500     #undef MAT_ROTATE
501     #undef MAX_ROTATIONS