Shapeworks Studio  2.1
Shape analysis software suite
math3d.cpp
1 #include "math3d.h"
2 
3 //-----------------------------------------------------------------------------
4 mat3d::mat3d(double a00, double a01, double a02, double a10, double a11, double a12, double a20, double a21, double a22)
5 {
6  m_data[0][0] = a00; m_data[0][1] = a01; m_data[0][2] = a02;
7  m_data[1][0] = a10; m_data[1][1] = a11; m_data[1][2] = a12;
8  m_data[2][0] = a20; m_data[2][1] = a21; m_data[2][2] = a22;
9 }
10 
11 //-----------------------------------------------------------------------------
12 double mat3d::Invert()
13 {
14  // calculate determinant
15  double det = 0;
16  det += m_data[0][0]*m_data[1][1]*m_data[2][2];
17  det += m_data[0][1]*m_data[1][2]*m_data[2][0];
18  det += m_data[0][2]*m_data[1][0]*m_data[2][1];
19  det -= m_data[0][2]*m_data[1][1]*m_data[2][0];
20  det -= m_data[0][1]*m_data[1][0]*m_data[2][2];
21  det -= m_data[0][0]*m_data[1][2]*m_data[2][1];
22 
23  assert(det != 0);
24 
25  double deti = 1 / det;
26 
27  // calculate conjugate matrix
28  double mi[3][3];
29 
30  mi[0][0] = (m_data[1][1]*m_data[2][2] - m_data[1][2]*m_data[2][1]);
31  mi[0][1] = -(m_data[1][0]*m_data[2][2] - m_data[1][2]*m_data[2][0]);
32  mi[0][2] = (m_data[1][0]*m_data[2][1] - m_data[1][1]*m_data[2][0]);
33 
34  mi[1][0] = -(m_data[0][1]*m_data[2][2] - m_data[0][2]*m_data[2][1]);
35  mi[1][1] = (m_data[0][0]*m_data[2][2] - m_data[0][2]*m_data[2][0]);
36  mi[1][2] = -(m_data[0][0]*m_data[2][1] - m_data[0][1]*m_data[2][0]);
37 
38  mi[2][0] = (m_data[0][1]*m_data[1][2] - m_data[0][2]*m_data[1][1]);
39  mi[2][1] = -(m_data[0][0]*m_data[1][2] - m_data[0][2]*m_data[1][0]);
40  mi[2][2] = (m_data[0][0]*m_data[1][1] - m_data[0][1]*m_data[1][0]);
41 
42  // divide by det and transpose
43  m_data[0][0] = mi[0][0]*deti; m_data[1][0] = mi[0][1]*deti; m_data[2][0] = mi[0][2]*deti;
44  m_data[0][1] = mi[1][0]*deti; m_data[1][1] = mi[1][1]*deti; m_data[2][1] = mi[1][2]*deti;
45  m_data[0][2] = mi[2][0]*deti; m_data[1][2] = mi[2][1]*deti; m_data[2][2] = mi[2][2]*deti;
46 
47  // return determinant
48  return det;
49 }
50 
51 //-----------------------------------------------------------------------------
52 quatd quatd::slerp(quatd &q1, quatd &q2, double t)
53 {
54  quatd q3;
55  double dot = quatd::dot(q1, q2);
56 
57  /* dot = cos(theta)
58  if (dot < 0), q1 and q2 are more than 90 degrees apart,
59  so we can invert one to reduce spinning */
60  if (dot < 0)
61  {
62  dot = -dot;
63  q3 = -q2;
64  } else q3 = q2;
65 
66  if (dot < 0.95f)
67  {
68  double angle = acos(dot);
69  return (q1*sin(angle*(1-t)) + q3*sin(angle*t))/sin(angle);
70  } else // if the angle is small, use linear interpolation
71  return quatd::lerp(q1,q3,t);
72 }
73 
74 
75 //-----------------------------------------------------------------------------
76 bool matrix::solve(vector<double>& x, vector<double>& b)
77 {
78  // check sizes
79  if (m_nr != m_nc) return false;
80  if (((int)x.size() != m_nr) || ((int)b.size() != m_nr)) return false;
81 
82  // step 1. Factorization
83 
84  const double TINY = 1.0e-20;
85  int i, imax, j, k;
86  double big, dum, sum, temp;
87 
88  matrix& a = *this;
89 
90  int n = a.Rows();
91 
92  // create index vector
93  vector<int> indx(n);
94 
95  vector<double> vv(n);
96  for (i=0; i<n; ++i)
97  {
98  big = 0;
99  for (j=0; j<n; ++j)
100  if ((temp=fabs(a(i,j))) > big) big = temp;
101  if (big == 0) return false; // singular matrix
102  vv[i] = 1.0 / big;
103  }
104 
105  for (j=0; j<n; ++j)
106  {
107  for (i=0; i<j; ++i)
108  {
109  sum = a(i,j);
110  for (k=0; k<i; ++k) sum -= a(i,k)*a(k,j);
111  a(i,j) = sum;
112  }
113  big = 0;
114  imax = j;
115  for (i=j;i<n;++i)
116  {
117  sum = a(i,j);
118  for (k=0; k<j; ++k) sum -= a(i,k)*a(k,j);
119  a(i,j) = sum;
120  if ((dum=vv[i]*fabs(sum))>=big)
121  {
122  big = dum;
123  imax = i;
124  }
125  }
126 
127  if (j != imax)
128  {
129  for (k=0; k<n; ++k)
130  {
131  dum = a(imax,k);
132  a(imax,k) = a(j,k);
133  a(j,k) = dum;
134  }
135  vv[imax] = vv[j];
136  }
137 
138  indx[j] = imax;
139  if (a(j,j) == 0) a(j,j) = TINY;
140  if (j != n-1)
141  {
142  dum = 1.0/a(j,j);
143  for (i=j+1;i<n; ++i) a(i,j) *= dum;
144  }
145  }
146 
147  // step 2. back-solve
148  x = b;
149 
150  int ii=0, ip;
151 
152  n = a.Rows();
153  for (i=0; i<n; ++i)
154  {
155  ip = indx[i];
156  sum = x[ip];
157  x[ip] = x[i];
158  if (ii != 0)
159  for (j=ii-1;j<i;++j) sum -= a(i,j)*x[j];
160  else if (sum != 0)
161  ii = i+1;
162  x[i] = sum;
163  }
164 
165  for (i=n-1; i>=0; --i)
166  {
167  sum = x[i];
168  for (j=i+1; j<n; ++j) sum -= a(i,j)*x[j];
169  x[i] = sum/a(i,i);
170  }
171 
172  return true;
173 }
174 //-----------------------------------------------------------------------------
175 void matrix::mult_transpose_self(matrix& AAt)
176 {
177  matrix& A = *this;
178  int N = m_nc;
179  int R = m_nr;
180  for (int i=0; i<N; ++i)
181  for (int j=0; j<N; ++j)
182  {
183  double& aij = AAt[i][j];
184  aij = 0.0;
185  for (int k=0; k<R; ++k) aij += A[k][i]*A[k][j];
186  }
187 }
188 //-----------------------------------------------------------------------------
189 matrix::matrix(int r, int c) : m_nr(r), m_nc(c)
190 {
191  m_ne = r*c;
192  if (m_ne > 0) d = new double[m_ne];
193  else d = 0;
194 }
195 
196 //-----------------------------------------------------------------------------
197 void matrix::zero()
198 {
199  for (int i=0; i<m_ne; ++i) d[i] = 0.0;
200 }
201 
202 //-----------------------------------------------------------------------------
203 void matrix::mult_transpose(vector<double>& x, vector<double>& y)
204 {
205  for (int i=0; i<m_nc; ++i) y[i] = 0.0;
206 
207  for (int i=0; i<m_nr; ++i)
208  {
209  double* di = d + i*m_nc;
210  for (int j=0; j<m_nc; ++j) y[j] += di[j]*x[i];
211  }
212 }
213 
214 //-----------------------------------------------------------------------------
215 bool matrix::lsq_solve(vector<double>& x, vector<double>& b)
216 {
217  if ((int) x.size() != m_nc) return false;
218  if ((int) b.size() != m_nr) return false;
219 
220  vector<double> y(m_nc);
221  mult_transpose(b, y);
222 
223  matrix AA(m_nc, m_nc);
224  mult_transpose_self(AA);
225 
226  AA.solve(x, y);
227 
228  return true;
229 }
230 
231 #define 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);
232 
233 bool matrix::eigen_vectors(matrix& Eigen, vector<double>& eigen_values){
234  matrix& A = *this;
235  int N = m_nc;
236  int R = m_nr;
237  const int NMAX = 50;
238  double sm, tresh, g, h, t, c, tau, s, th;
239  const double eps = 0;//1.0e-15;
240  int k ;
241 
242  //initialize Eigen to identity
243  for(int i = 0; i< R ; i++)
244  {
245  for(int j = 0;j<N;j++) Eigen[i][j] = 0;
246  Eigen[i][i] = 1;
247  }
248  vector<double> b;
249  b.reserve(R);
250  vector<double> z;
251  z.reserve(R);
252 
253  // initialize b and eigen_values to the diagonal of A
254  for(int i = 0; i<R;i++)
255  {
256  b.push_back(A[i][i]);
257  eigen_values.push_back(A[i][i]);
258  z.push_back(0);
259  }
260  // loop
261  int n, nrot = 0;
262  for (n=0; n<NMAX; ++n)
263  {
264  // sum off-diagonal elements
265  sm = 0;
266  for(int i = 0; i<N-1;i++){
267  for(int j = i+1; j<N; j++)
268  sm += fabs(A[i][j]);
269  }
270  if (sm <= eps) {
271  break;
272  }
273  // set the treshold
274  if (n < 3) tresh = 0.2*sm/(R*R); else tresh = 0.0;
275 
276  // loop over off-diagonal elements
277  for(int i = 0; i<N-1;i++){
278  for(int j = i+1; j<N; j++){
279 
280  g = 100.0*fabs(A[i][j]);
281  // after four sweeps, skip the rotation if the off-diagonal element is small
282  if ((n > 3) && ((fabs(eigen_values[i])+g) == fabs(eigen_values[i])) && ((fabs(eigen_values[j])+g) == fabs(eigen_values[j])))
283  {
284  A[i][j] = 0.0;
285  }
286  else if (fabs(A[i][j]) > tresh){
287  h = eigen_values[j] - eigen_values[i];
288  if ((fabs(h)+g) == fabs(h))
289  t = A[i][j]/h;
290  else
291  {
292  th = 0.5*h/A[i][j];
293  t = 1.0/(fabs(th) + sqrt(1+th*th));
294  if (th < 0.0) t = -t;
295  }
296  c = 1.0/sqrt(1.0 + t*t);
297  s = t*c;
298  tau = s/(1.0+c);
299  h = t*A[i][j];
300  z[i] -= h;
301  z[j] += h;
302  eigen_values[i] -= h;
303  eigen_values[j] += h;
304  A[i][j] = 0;
305  for (k= 0; k<=i-1; ++k) { ROTATE(A, k, i, k, j) }
306  for (k=i+1; k<=j-1; ++k) { ROTATE(A, i, k, k, j) }
307  for (k=j+1; k<N; ++k) { ROTATE(A, i, k, j, k) }
308  for (k= 0; k<N; ++k) { ROTATE(Eigen, k, i, k, j) }
309  ++nrot;
310  }
311  }
312  }//end of for loop
313 
314  //Update eigen_values with the sum. Reinitialize z.
315  for (int i=0; i<R; ++i)
316  {
317  b[i] += z[i];
318  eigen_values[i] = b[i];
319  z[i] = 0.0;
320  }
321  }
322 
323  // we sure we converged
324  assert(n < NMAX);
325  return true;
326 }
327 //-----------------------------------------------------------------------------
328 mat3d mat3d::transpose()
329 {
330  return mat3d(m_data[0][0], m_data[1][0], m_data[2][0], m_data[0][1], m_data[1][1], m_data[2][1], m_data[0][2], m_data[1][2], m_data[2][2]);
331 }
Definition: math3d.h:219
Definition: math3d.h:250
Definition: math3d.h:97
Definition: LDLT.h:16