~ubuntu-branches/ubuntu/maverick/freecad/maverick

« back to all changes in this revision

Viewing changes to src/Base/Matrix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Teemu Ikonen
  • Date: 2009-07-16 18:37:41 UTC
  • Revision ID: james.westby@ubuntu.com-20090716183741-oww9kcxqrk991i1n
Tags: upstream-0.8.2237
ImportĀ upstreamĀ versionĀ 0.8.2237

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (c) 2005 Imetric 3D GmbH                                    *
 
3
 *                                                                         *
 
4
 *   This file is part of the FreeCAD CAx development system.              *
 
5
 *                                                                         *
 
6
 *   This library is free software; you can redistribute it and/or         *
 
7
 *   modify it under the terms of the GNU Library General Public           *
 
8
 *   License as published by the Free Software Foundation; either          *
 
9
 *   version 2 of the License, or (at your option) any later version.      *
 
10
 *                                                                         *
 
11
 *   This library  is distributed in the hope that it will be useful,      *
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
14
 *   GNU Library General Public License for more details.                  *
 
15
 *                                                                         *
 
16
 *   You should have received a copy of the GNU Library General Public     *
 
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
 
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 
20
 *                                                                         *
 
21
 ***************************************************************************/
 
22
 
 
23
 
 
24
#include "PreCompiled.h"
 
25
#ifndef _PreComp_
 
26
# include <memory>
 
27
# include <cstring>
 
28
# include <sstream>
 
29
#endif
 
30
 
 
31
 
 
32
#include "Matrix.h"
 
33
 
 
34
using namespace Base;
 
35
 
 
36
Matrix4D::Matrix4D (void)
 
37
{
 
38
  setToUnity();
 
39
}
 
40
 
 
41
Matrix4D::Matrix4D (float a11, float a12, float a13, float a14, 
 
42
                    float a21, float a22, float a23, float a24,
 
43
                    float a31, float a32, float a33, float a34,
 
44
                    float a41, float a42, float a43, float a44 )
 
45
{
 
46
  dMtrx4D[0][0] = a11; dMtrx4D[0][1] = a12; dMtrx4D[0][2] = a13; dMtrx4D[0][3] = a14;
 
47
  dMtrx4D[1][0] = a21; dMtrx4D[1][1] = a22; dMtrx4D[1][2] = a23; dMtrx4D[1][3] = a24;
 
48
  dMtrx4D[2][0] = a31; dMtrx4D[2][1] = a32; dMtrx4D[2][2] = a33; dMtrx4D[2][3] = a34;
 
49
  dMtrx4D[3][0] = a41; dMtrx4D[3][1] = a42; dMtrx4D[3][2] = a43; dMtrx4D[3][3] = a44;
 
50
}
 
51
 
 
52
Matrix4D::Matrix4D (double a11, double a12, double a13, double a14, 
 
53
                    double a21, double a22, double a23, double a24,
 
54
                    double a31, double a32, double a33, double a34,
 
55
                    double a41, double a42, double a43, double a44 )
 
56
{
 
57
  dMtrx4D[0][0] = a11; dMtrx4D[0][1] = a12; dMtrx4D[0][2] = a13; dMtrx4D[0][3] = a14;
 
58
  dMtrx4D[1][0] = a21; dMtrx4D[1][1] = a22; dMtrx4D[1][2] = a23; dMtrx4D[1][3] = a24;
 
59
  dMtrx4D[2][0] = a31; dMtrx4D[2][1] = a32; dMtrx4D[2][2] = a33; dMtrx4D[2][3] = a34;
 
60
  dMtrx4D[3][0] = a41; dMtrx4D[3][1] = a42; dMtrx4D[3][2] = a43; dMtrx4D[3][3] = a44;
 
61
}
 
62
 
 
63
 
 
64
Matrix4D::Matrix4D (const Matrix4D& rclMtrx)
 
65
{
 
66
  (*this) = rclMtrx;
 
67
}
 
68
 
 
69
Matrix4D::Matrix4D (const Vector3f& rclBase, const Vector3f& rclDir, float fAngle)
 
70
{
 
71
  setToUnity();
 
72
  this->rotLine(rclBase,rclDir,fAngle);
 
73
}
 
74
 
 
75
void Matrix4D::setToUnity (void)
 
76
{
 
77
  dMtrx4D[0][0] = 1.0; dMtrx4D[0][1] = 0.0; dMtrx4D[0][2] = 0.0; dMtrx4D[0][3] = 0.0;
 
78
  dMtrx4D[1][0] = 0.0; dMtrx4D[1][1] = 1.0; dMtrx4D[1][2] = 0.0; dMtrx4D[1][3] = 0.0;
 
79
  dMtrx4D[2][0] = 0.0; dMtrx4D[2][1] = 0.0; dMtrx4D[2][2] = 1.0; dMtrx4D[2][3] = 0.0;
 
80
  dMtrx4D[3][0] = 0.0; dMtrx4D[3][1] = 0.0; dMtrx4D[3][2] = 0.0; dMtrx4D[3][3] = 1.0;
 
81
}
 
82
 
 
83
double Matrix4D::determinant() const
 
84
{
 
85
    double fA0 = dMtrx4D[0][0]*dMtrx4D[1][1] - dMtrx4D[0][1]*dMtrx4D[1][0];
 
86
    double fA1 = dMtrx4D[0][0]*dMtrx4D[1][2] - dMtrx4D[0][2]*dMtrx4D[1][0];
 
87
    double fA2 = dMtrx4D[0][0]*dMtrx4D[1][3] - dMtrx4D[0][3]*dMtrx4D[1][0];
 
88
    double fA3 = dMtrx4D[0][1]*dMtrx4D[1][2] - dMtrx4D[0][2]*dMtrx4D[1][1];
 
89
    double fA4 = dMtrx4D[0][1]*dMtrx4D[1][3] - dMtrx4D[0][3]*dMtrx4D[1][1];
 
90
    double fA5 = dMtrx4D[0][2]*dMtrx4D[1][3] - dMtrx4D[0][3]*dMtrx4D[1][2];
 
91
    double fB0 = dMtrx4D[2][0]*dMtrx4D[3][1] - dMtrx4D[2][1]*dMtrx4D[3][0];
 
92
    double fB1 = dMtrx4D[2][0]*dMtrx4D[3][2] - dMtrx4D[2][2]*dMtrx4D[3][0];
 
93
    double fB2 = dMtrx4D[2][0]*dMtrx4D[3][3] - dMtrx4D[2][3]*dMtrx4D[3][0];
 
94
    double fB3 = dMtrx4D[2][1]*dMtrx4D[3][2] - dMtrx4D[2][2]*dMtrx4D[3][1];
 
95
    double fB4 = dMtrx4D[2][1]*dMtrx4D[3][3] - dMtrx4D[2][3]*dMtrx4D[3][1];
 
96
    double fB5 = dMtrx4D[2][2]*dMtrx4D[3][3] - dMtrx4D[2][3]*dMtrx4D[3][2];
 
97
    double fDet = fA0*fB5-fA1*fB4+fA2*fB3+fA3*fB2-fA4*fB1+fA5*fB0;
 
98
    return fDet;
 
99
}
 
100
 
 
101
/*
 
102
void Matrix4D::setMoveX (float fMove)
 
103
{
 
104
  Matrix4D clMat;
 
105
 
 
106
  clMat.dMtrx4D[0][3] = fMove;
 
107
  (*this) *= clMat;
 
108
}
 
109
 
 
110
void Matrix4D::setMoveY (float fMove)
 
111
{
 
112
  Matrix4D clMat;
 
113
 
 
114
  clMat.dMtrx4D[1][3] = fMove;
 
115
  (*this) *= clMat;
 
116
}
 
117
 
 
118
void Matrix4D::setMoveZ (float fMove)
 
119
{
 
120
  Matrix4D clMat;
 
121
 
 
122
  clMat.dMtrx4D[2][3] = fMove;
 
123
  (*this) *= clMat;
 
124
}
 
125
*/
 
126
void Matrix4D::move (const Vector3f& rclVct)
 
127
{
 
128
  Matrix4D clMat;
 
129
 
 
130
  clMat.dMtrx4D[0][3] = rclVct.x;
 
131
  clMat.dMtrx4D[1][3] = rclVct.y;
 
132
  clMat.dMtrx4D[2][3] = rclVct.z;
 
133
  (*this) *= clMat;
 
134
}
 
135
void Matrix4D::move (const Vector3d& rclVct)
 
136
{
 
137
  Matrix4D clMat;
 
138
 
 
139
  clMat.dMtrx4D[0][3] = rclVct.x;
 
140
  clMat.dMtrx4D[1][3] = rclVct.y;
 
141
  clMat.dMtrx4D[2][3] = rclVct.z;
 
142
  (*this) *= clMat;
 
143
}
 
144
/*
 
145
void Matrix4D::setScaleX (float fScale)
 
146
{
 
147
  Matrix4D clMat;
 
148
 
 
149
  clMat.dMtrx4D[0][0] = fScale;
 
150
  
 
151
  (*this) *= clMat;
 
152
}
 
153
 
 
154
void Matrix4D::setScaleY (float fScale)
 
155
{
 
156
  Matrix4D clMat;
 
157
 
 
158
  clMat.dMtrx4D[1][1] = fScale;
 
159
  (*this) *= clMat;
 
160
}
 
161
 
 
162
void Matrix4D::setScaleZ (float fScale)
 
163
{
 
164
  Matrix4D clMat;
 
165
 
 
166
  clMat.dMtrx4D[2][2] = fScale;
 
167
  (*this) *= clMat;
 
168
}
 
169
*/
 
170
 
 
171
void Matrix4D::scale (const Vector3f& rclVct)
 
172
{
 
173
  Matrix4D clMat;
 
174
 
 
175
  clMat.dMtrx4D[0][0] = rclVct.x;
 
176
  clMat.dMtrx4D[1][1] = rclVct.y;
 
177
  clMat.dMtrx4D[2][2] = rclVct.z;
 
178
  (*this) *= clMat;
 
179
}
 
180
void Matrix4D::scale (const Vector3d& rclVct)
 
181
{
 
182
  Matrix4D clMat;
 
183
 
 
184
  clMat.dMtrx4D[0][0] = rclVct.x;
 
185
  clMat.dMtrx4D[1][1] = rclVct.y;
 
186
  clMat.dMtrx4D[2][2] = rclVct.z;
 
187
  (*this) *= clMat;
 
188
}
 
189
 
 
190
void Matrix4D::rotX (double fAngle)
 
191
{
 
192
  Matrix4D clMat;
 
193
  double fsin, fcos;
 
194
 
 
195
  fsin = sin (fAngle);
 
196
  fcos = cos (fAngle);
 
197
  clMat.dMtrx4D[1][1] =  fcos;  clMat.dMtrx4D[2][2] = fcos;
 
198
  clMat.dMtrx4D[1][2] = -fsin;  clMat.dMtrx4D[2][1] = fsin;
 
199
  
 
200
  (*this) *= clMat;
 
201
}
 
202
 
 
203
void Matrix4D::rotY (double fAngle)
 
204
{
 
205
  Matrix4D clMat;
 
206
  double fsin, fcos;
 
207
 
 
208
  fsin = sin (fAngle);
 
209
  fcos = cos (fAngle);
 
210
  clMat.dMtrx4D[0][0] =  fcos;  clMat.dMtrx4D[2][2] = fcos;
 
211
  clMat.dMtrx4D[2][0] = -fsin;  clMat.dMtrx4D[0][2] = fsin;
 
212
  
 
213
  (*this) *= clMat;
 
214
}
 
215
 
 
216
void Matrix4D::rotZ (double fAngle)
 
217
{
 
218
  Matrix4D clMat;
 
219
  double fsin, fcos;
 
220
 
 
221
  fsin = sin (fAngle);
 
222
  fcos = cos (fAngle);
 
223
  clMat.dMtrx4D[0][0] =  fcos;  clMat.dMtrx4D[1][1] = fcos;
 
224
  clMat.dMtrx4D[0][1] = -fsin;  clMat.dMtrx4D[1][0] = fsin;
 
225
  
 
226
  (*this) *= clMat;
 
227
}
 
228
 
 
229
void Matrix4D::rotLine (const Vector3d& rclVct, double fAngle)
 
230
{
 
231
  // **** algorithm was taken from a math book
 
232
  Matrix4D  clMA, clMB, clMC, clMRot;
 
233
  Vector3d  clRotAxis(rclVct);
 
234
  short iz, is;
 
235
  double fcos, fsin;
 
236
 
 
237
  // set all entries to "0"
 
238
  for (iz = 0; iz < 4; iz++)
 
239
    for (is = 0; is < 4; is++)  {
 
240
      clMA.dMtrx4D[iz][is] = 0;
 
241
      clMB.dMtrx4D[iz][is] = 0;
 
242
      clMC.dMtrx4D[iz][is] = 0;
 
243
    }
 
244
 
 
245
  // ** normalize the rotation axis
 
246
  clRotAxis.Normalize();
 
247
  
 
248
  // ** set the rotation matrix (formula taken from a math book) */
 
249
  fcos = cos(fAngle);
 
250
  fsin = sin(fAngle);
 
251
  
 
252
  clMA.dMtrx4D[0][0] = (1-fcos) * clRotAxis.x * clRotAxis.x;
 
253
  clMA.dMtrx4D[0][1] = (1-fcos) * clRotAxis.x * clRotAxis.y;
 
254
  clMA.dMtrx4D[0][2] = (1-fcos) * clRotAxis.x * clRotAxis.z;
 
255
  clMA.dMtrx4D[1][0] = (1-fcos) * clRotAxis.x * clRotAxis.y;
 
256
  clMA.dMtrx4D[1][1] = (1-fcos) * clRotAxis.y * clRotAxis.y;
 
257
  clMA.dMtrx4D[1][2] = (1-fcos) * clRotAxis.y * clRotAxis.z;
 
258
  clMA.dMtrx4D[2][0] = (1-fcos) * clRotAxis.x * clRotAxis.z;
 
259
  clMA.dMtrx4D[2][1] = (1-fcos) * clRotAxis.y * clRotAxis.z;
 
260
  clMA.dMtrx4D[2][2] = (1-fcos) * clRotAxis.z * clRotAxis.z;
 
261
 
 
262
  clMB.dMtrx4D[0][0] = fcos;
 
263
  clMB.dMtrx4D[1][1] = fcos;
 
264
  clMB.dMtrx4D[2][2] = fcos;
 
265
 
 
266
  clMC.dMtrx4D[0][1] = -fsin * clRotAxis.z;
 
267
  clMC.dMtrx4D[0][2] =  fsin * clRotAxis.y;
 
268
  clMC.dMtrx4D[1][0] =  fsin * clRotAxis.z;
 
269
  clMC.dMtrx4D[1][2] = -fsin * clRotAxis.x;
 
270
  clMC.dMtrx4D[2][0] = -fsin * clRotAxis.y;
 
271
  clMC.dMtrx4D[2][1] =  fsin * clRotAxis.x;
 
272
 
 
273
  for (iz = 0; iz < 3; iz++)
 
274
    for (is = 0; is < 3; is++)
 
275
      clMRot.dMtrx4D[iz][is] = clMA.dMtrx4D[iz][is]  + clMB.dMtrx4D[iz][is] +
 
276
                               clMC.dMtrx4D[iz][is];
 
277
  (*this) *= clMRot;
 
278
}
 
279
 
 
280
void Matrix4D::rotLine (const Vector3f& rclVct, float fAngle)
 
281
{
 
282
    Vector3d tmp(rclVct.x,rclVct.y,rclVct.z);
 
283
    rotLine(tmp,fAngle);
 
284
}
 
285
 
 
286
void Matrix4D::rotLine(const Vector3d& rclBase, const Vector3d& rclDir, double fAngle)
 
287
{
 
288
  Matrix4D  clMT, clMRot, clMInvT, clM;
 
289
  Vector3d clBase(rclBase);
 
290
  
 
291
  clMT.move(clBase);            // Translation
 
292
  clMInvT.move(clBase *= (-1.0f));  // inverse Translation
 
293
  clMRot.rotLine(rclDir, fAngle);
 
294
 
 
295
  clM = clMRot * clMInvT;
 
296
  clM = clMT * clM; 
 
297
  (*this) *= clM;  
 
298
}
 
299
 
 
300
void Matrix4D::rotLine   (const Vector3f& rclBase, const Vector3f& rclDir, float fAngle)
 
301
{
 
302
  Matrix4D  clMT, clMRot, clMInvT, clM;
 
303
  Vector3f clBase(rclBase);
 
304
  
 
305
  clMT.move(clBase);            // Translation
 
306
  clMInvT.move(clBase *= (-1.0f));  // inverse Translation
 
307
  clMRot.rotLine(rclDir, fAngle);
 
308
 
 
309
  clM = clMRot * clMInvT;
 
310
  clM = clMT * clM; 
 
311
  (*this) *= clM;  
 
312
}
 
313
 
 
314
/**
 
315
 * If this matrix describes a rotation around an arbitrary axis with a translation (in axis direction)
 
316
 * then the base point of the axis, its direction, the rotation angle and the translation part get calculated.
 
317
 * In this case the return value is set to true, if this matrix doesn't describe a rotation false is returned. 
 
318
 *
 
319
 * The translation vector can be calculated with \a fTranslation * \a rclDir, whereas the length of \a rclDir
 
320
 * is normalized to 1.
 
321
 *
 
322
 * Note: In case the \a fTranslation part is zero then passing \a rclBase, \a rclDir and \a rfAngle to a new
 
323
 * matrix object creates an identical matrix.
 
324
 */
 
325
bool Matrix4D::toAxisAngle (Vector3f& rclBase, Vector3f& rclDir, float& rfAngle, float& fTranslation) const
 
326
{
 
327
  // First check if the 3x3 submatrix is orthogonal
 
328
  for ( int i=0; i<3; i++ ) {
 
329
    // length must be one
 
330
    if ( fabs(dMtrx4D[0][i]*dMtrx4D[0][i]+dMtrx4D[1][i]*dMtrx4D[1][i]+dMtrx4D[2][i]*dMtrx4D[2][i]-1.0) > 0.01 )
 
331
      return false;
 
332
    // scalar product with other rows must be zero
 
333
    if ( fabs(dMtrx4D[0][i]*dMtrx4D[0][(i+1)%3]+dMtrx4D[1][i]*dMtrx4D[1][(i+1)%3]+dMtrx4D[2][i]*dMtrx4D[2][(i+1)%3]) > 0.01 )
 
334
      return false;
 
335
  }
 
336
 
 
337
  // Okay, the 3x3 matrix is orthogonal.
 
338
  // Note: The section to get the rotation axis and angle was taken from WildMagic Library.
 
339
  //
 
340
  // Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
 
341
  // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where
 
342
  // I is the identity and
 
343
  //
 
344
  //       +-        -+
 
345
  //   P = |  0 -z +y |
 
346
  //       | +z  0 -x |
 
347
  //       | -y +x  0 |
 
348
  //       +-        -+
 
349
  //
 
350
  // If A > 0, R represents a counterclockwise rotation about the axis in
 
351
  // the sense of looking from the tip of the axis vector towards the
 
352
  // origin.  Some algebra will show that
 
353
  //
 
354
  //   cos(A) = (trace(R)-1)/2  and  R - R^t = 2*sin(A)*P
 
355
  //
 
356
  // In the event that A = pi, R-R^t = 0 which prevents us from extracting
 
357
  // the axis through P.  Instead note that R = I+2*P^2 when A = pi, so
 
358
  // P^2 = (R-I)/2.  The diagonal entries of P^2 are x^2-1, y^2-1, and
 
359
  // z^2-1.  We can solve these for axis (x,y,z).  Because the angle is pi,
 
360
  // it does not matter which sign you choose on the square roots.
 
361
  //
 
362
  // For more details see also http://www.math.niu.edu/~rusin/known-math/97/rotations
 
363
 
 
364
  double fTrace = dMtrx4D[0][0] + dMtrx4D[1][1] + dMtrx4D[2][2];
 
365
  double fCos = 0.5*(fTrace-1.0);
 
366
  rfAngle = (float)acos(fCos);  // in [0,PI]
 
367
 
 
368
  if ( rfAngle > 0.0f )
 
369
  {
 
370
    if ( rfAngle < F_PI )
 
371
    {
 
372
      rclDir.x = (float)(dMtrx4D[2][1]-dMtrx4D[1][2]);
 
373
      rclDir.y = (float)(dMtrx4D[0][2]-dMtrx4D[2][0]);
 
374
      rclDir.z = (float)(dMtrx4D[1][0]-dMtrx4D[0][1]);
 
375
      rclDir.Normalize();
 
376
    }
 
377
    else
 
378
    {
 
379
      // angle is PI
 
380
      double fHalfInverse;
 
381
      if ( dMtrx4D[0][0] >= dMtrx4D[1][1] )
 
382
      {
 
383
        // r00 >= r11
 
384
        if ( dMtrx4D[0][0] >= dMtrx4D[2][2] )
 
385
        {
 
386
          // r00 is maximum diagonal term
 
387
          rclDir.x = (float)(0.5*sqrt(dMtrx4D[0][0] - dMtrx4D[1][1] - dMtrx4D[2][2] + 1.0));
 
388
          fHalfInverse = 0.5/rclDir.x;
 
389
          rclDir.y = (float)(fHalfInverse*dMtrx4D[0][1]);
 
390
          rclDir.z = (float)(fHalfInverse*dMtrx4D[0][2]);
 
391
        }
 
392
        else
 
393
        {
 
394
          // r22 is maximum diagonal term
 
395
          rclDir.z = (float)(0.5*sqrt(dMtrx4D[2][2] - dMtrx4D[0][0] - dMtrx4D[1][1] + 1.0));
 
396
          fHalfInverse = 0.5/rclDir.z;
 
397
          rclDir.x = (float)(fHalfInverse*dMtrx4D[0][2]);
 
398
          rclDir.y = (float)(fHalfInverse*dMtrx4D[1][2]);
 
399
        }
 
400
      }
 
401
      else
 
402
      {
 
403
        // r11 > r00
 
404
        if ( dMtrx4D[1][1] >= dMtrx4D[2][2] )
 
405
        {
 
406
          // r11 is maximum diagonal term
 
407
          rclDir.y = (float)(0.5*sqrt(dMtrx4D[1][1] - dMtrx4D[0][0] - dMtrx4D[2][2] + 1.0));
 
408
          fHalfInverse  = 0.5/rclDir.y;
 
409
          rclDir.x = (float)(fHalfInverse*dMtrx4D[0][1]);
 
410
          rclDir.z = (float)(fHalfInverse*dMtrx4D[1][2]);
 
411
        }
 
412
        else
 
413
        {
 
414
          // r22 is maximum diagonal term
 
415
          rclDir.z = (float)(0.5*sqrt(dMtrx4D[2][2] - dMtrx4D[0][0] - dMtrx4D[1][1] + 1.0));
 
416
          fHalfInverse = 0.5/rclDir.z;
 
417
          rclDir.x = (float)(fHalfInverse*dMtrx4D[0][2]);
 
418
          rclDir.y = (float)(fHalfInverse*dMtrx4D[1][2]);
 
419
        }
 
420
      }
 
421
    }
 
422
  }
 
423
  else
 
424
  {
 
425
    // The angle is 0 and the matrix is the identity.  Any axis will
 
426
    // work, so just use the x-axis.
 
427
    rclDir.x = 1.0f;
 
428
    rclDir.y = 0.0f;
 
429
    rclDir.z = 0.0f;
 
430
    rclBase.x = 0.0f;
 
431
    rclBase.y = 0.0f;
 
432
    rclBase.z = 0.0f;
 
433
  }
 
434
 
 
435
  // This is the translation part in axis direction
 
436
  fTranslation = (float)(dMtrx4D[0][3]*rclDir.x+dMtrx4D[1][3]*rclDir.y+dMtrx4D[2][3]*rclDir.z);
 
437
  Vector3f cPnt((float)dMtrx4D[0][3],(float)dMtrx4D[1][3],(float)dMtrx4D[2][3]); 
 
438
  cPnt = cPnt - fTranslation * rclDir;
 
439
 
 
440
  // This is the base point of the rotation axis
 
441
  if ( rfAngle > 0.0f )
 
442
  {
 
443
    double factor = 0.5*(1.0+fTrace)/sin(rfAngle);
 
444
    rclBase.x = (float)(0.5*(cPnt.x+factor*(rclDir.y*cPnt.z-rclDir.z*cPnt.y)));
 
445
    rclBase.y = (float)(0.5*(cPnt.y+factor*(rclDir.z*cPnt.x-rclDir.x*cPnt.z)));
 
446
    rclBase.z = (float)(0.5*(cPnt.z+factor*(rclDir.x*cPnt.y-rclDir.y*cPnt.x)));
 
447
  }
 
448
 
 
449
  return true;
 
450
}
 
451
 
 
452
void Matrix4D::transform (const Vector3f& rclVct, const Matrix4D& rclMtrx)
 
453
{
 
454
  move(-rclVct);
 
455
  (*this) *= rclMtrx;
 
456
  move(rclVct);
 
457
}
 
458
void Matrix4D::transform (const Vector3d& rclVct, const Matrix4D& rclMtrx)
 
459
{
 
460
  move(-rclVct);
 
461
  (*this) *= rclMtrx;
 
462
  move(rclVct);
 
463
}
 
464
 
 
465
void Matrix4D::inverse (void)
 
466
{
 
467
  Matrix4D clInvTrlMat, clInvRotMat;
 
468
  short  iz, is;
 
469
 
 
470
  /**** Herausnehmen und Inversion der TranslationsMatrix
 
471
  aus der TransformationMatrix                      ****/
 
472
  for (iz = 0 ;iz < 3; iz++)
 
473
    clInvTrlMat.dMtrx4D[iz][3] = -dMtrx4D[iz][3];
 
474
 
 
475
  /**** Herausnehmen und Inversion der RotationsMatrix
 
476
  aus der TransformationMatrix                      ****/
 
477
  for (iz = 0 ;iz < 3; iz++)
 
478
    for (is = 0 ;is < 3; is++)
 
479
      clInvRotMat.dMtrx4D[iz][is] = dMtrx4D[is][iz];
 
480
      
 
481
  /**** inv(M) = inv(Mtrl * Mrot) = inv(Mrot) * inv(Mtrl) ****/
 
482
  (*this) = clInvRotMat * clInvTrlMat;
 
483
}
 
484
 
 
485
typedef  double * Matrix;
 
486
 
 
487
void Matrix_gauss(Matrix a, Matrix b)
 
488
{
 
489
  int ipiv[4], indxr[4], indxc[4];
 
490
  int i,j,k,l,ll;
 
491
  int irow=0, icol=0;
 
492
  double big, pivinv;
 
493
  double dum;
 
494
  for (j = 0; j < 4; j++)
 
495
    ipiv[j] = 0;
 
496
  for (i = 0; i < 4; i++) {
 
497
    big = 0;
 
498
    for (j = 0; j < 4; j++) {
 
499
      if (ipiv[j] != 1) {
 
500
  for (k = 0; k < 4; k++) {
 
501
    if (ipiv[k] == 0) {
 
502
      if (fabs(a[4*j+k]) >= big) {
 
503
        big = fabs(a[4*j+k]);
 
504
        irow = j;
 
505
        icol = k;
 
506
      }
 
507
    } else if (ipiv[k] > 1)
 
508
      return;  /* Singular matrix */
 
509
  }
 
510
      }
 
511
    }
 
512
    ipiv[icol] = ipiv[icol]+1;
 
513
    if (irow != icol) {
 
514
      for (l = 0; l < 4; l++) {
 
515
  dum = a[4*irow+l];
 
516
  a[4*irow+l] = a[4*icol+l];
 
517
  a[4*icol+l] = dum;
 
518
      }
 
519
      for (l = 0; l < 4; l++) {
 
520
  dum = b[4*irow+l];
 
521
  b[4*irow+l] = b[4*icol+l];
 
522
  b[4*icol+l] = dum;
 
523
      }
 
524
    }
 
525
    indxr[i] = irow;
 
526
    indxc[i] = icol;
 
527
    if (a[4*icol+icol] == 0) return;
 
528
    pivinv = 1.0/a[4*icol+icol];
 
529
    a[4*icol+icol] = 1.0;
 
530
    for (l = 0; l < 4; l++)
 
531
      a[4*icol+l] = a[4*icol+l]*pivinv;
 
532
    for (l = 0; l < 4; l++)
 
533
      b[4*icol+l] = b[4*icol+l]*pivinv;
 
534
    for (ll = 0; ll < 4; ll++) {
 
535
      if (ll != icol) {
 
536
  dum = a[4*ll+icol];
 
537
  a[4*ll+icol] = 0;
 
538
  for (l = 0; l < 4; l++)
 
539
    a[4*ll+l] = a[4*ll+l] - a[4*icol+l]*dum;
 
540
  for (l = 0; l < 4; l++)
 
541
    b[4*ll+l] = b[4*ll+l] - b[4*icol+l]*dum;
 
542
      }
 
543
    }
 
544
  }
 
545
  for (l = 3; l >= 0; l--) {
 
546
    if (indxr[l] != indxc[l]) {
 
547
      for (k = 0; k < 4; k++) {
 
548
  dum = a[4*k+indxr[l]];
 
549
  a[4*k+indxr[l]] = a[4*k+indxc[l]];
 
550
  a[4*k+indxc[l]] = dum;
 
551
      }
 
552
    }
 
553
  }
 
554
}
 
555
/* ------------------------------------------------------------------------
 
556
   Matrix_identity(Matrix a)
 
557
 
 
558
   Puts an identity matrix in matrix a
 
559
   ------------------------------------------------------------------------ */
 
560
 
 
561
void Matrix_identity (Matrix a)
 
562
{
 
563
  int i;
 
564
  for (i = 0; i < 16; i++) a[i] = 0;
 
565
  a[0] = 1;
 
566
  a[5] = 1;
 
567
  a[10] = 1;
 
568
  a[15] = 1;
 
569
}
 
570
 
 
571
/* ------------------------------------------------------------------------
 
572
   Matrix_invert(Matrix a, Matrix inva)
 
573
 
 
574
   Inverts Matrix a and places the result in inva.
 
575
   Relies on the Gaussian Elimination code above. (See Numerical recipes).
 
576
   ------------------------------------------------------------------------ */
 
577
void Matrix_invert (Matrix a, Matrix inva)
 
578
{
 
579
 
 
580
  double  temp[16];
 
581
  int     i;
 
582
 
 
583
  for (i = 0; i < 16; i++)
 
584
    temp[i] = a[i];
 
585
  Matrix_identity(inva);
 
586
  Matrix_gauss(temp,inva);
 
587
}
 
588
 
 
589
void Matrix4D::inverseGauss (void)
 
590
{
 
591
  double matrix        [16]; 
 
592
  double inversematrix [16] = { 1 ,0 ,0 ,0 ,
 
593
                                0 ,1 ,0 ,0 ,
 
594
                                0 ,0 ,1 ,0 ,
 
595
                                0 ,0 ,0 ,1 }; 
 
596
  getGLMatrix(matrix);
 
597
 
 
598
//  Matrix_invert(matrix, inversematrix);
 
599
  Matrix_gauss(matrix,inversematrix);
 
600
 
 
601
  setGLMatrix(inversematrix);
 
602
}
 
603
 
 
604
void Matrix4D::getGLMatrix (double dMtrx[16]) const
 
605
{
 
606
  short iz, is;
 
607
 
 
608
  for (iz = 0; iz < 4; iz++)
 
609
    for (is = 0; is < 4; is++)
 
610
      dMtrx[ iz + 4*is ] = dMtrx4D[iz][is];
 
611
}
 
612
 
 
613
void Matrix4D::setGLMatrix (const double dMtrx[16])
 
614
{
 
615
  short iz, is;
 
616
 
 
617
  for (iz = 0; iz < 4; iz++)
 
618
    for (is = 0; is < 4; is++)
 
619
      dMtrx4D[iz][is] = dMtrx[ iz + 4*is ];
 
620
}
 
621
 
 
622
unsigned long Matrix4D::getMemSpace (void)
 
623
{
 
624
  return sizeof(Matrix4D);
 
625
}
 
626
 
 
627
void Matrix4D::Print (void) const
 
628
{
 
629
  short i;
 
630
 
 
631
  for (i = 0; i < 4; i++)
 
632
    printf("%9.3f %9.3f %9.3f %9.3f\n", dMtrx4D[i][0], dMtrx4D[i][1], dMtrx4D[i][2], dMtrx4D[i][3]);
 
633
}
 
634
 
 
635
void Matrix4D::transpose (void)
 
636
{
 
637
  double  dNew[4][4];
 
638
 
 
639
  for (int i = 0; i < 4; i++)
 
640
  {
 
641
    for (int j = 0; j < 4; j++)
 
642
      dNew[j][i] = dMtrx4D[i][j];
 
643
  }
 
644
 
 
645
  memcpy(dMtrx4D, dNew, sizeof(dMtrx4D));
 
646
}
 
647
 
 
648
 
 
649
 
 
650
// write the 12 double of the matrix in a stream
 
651
std::string Matrix4D::toString(void) const
 
652
{
 
653
  std::stringstream str;
 
654
  for (int i = 0; i < 4; i++)
 
655
  {
 
656
    for (int j = 0; j < 4; j++)
 
657
      str << dMtrx4D[i][j] << " ";
 
658
  }
 
659
    
 
660
  return str.str();
 
661
}
 
662
 
 
663
// read the 12 double of the matrix from a stream
 
664
void Matrix4D::fromString(const std::string &str)
 
665
{
 
666
  std::stringstream input;
 
667
  input.str(str);
 
668
 
 
669
  for (int i = 0; i < 4; i++)
 
670
  {
 
671
    for (int j = 0; j < 4; j++)
 
672
      input >> dMtrx4D[i][j];
 
673
  }    
 
674
}