Wm4Eigen.cpp

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.0 (2006/06/28)
00016 
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4Eigen.h"
00019 
00020 namespace Wm4
00021 {
00022 //----------------------------------------------------------------------------
00023 template <class Real>
00024 Eigen<Real>::Eigen (int iSize)
00025     :
00026     m_kMat(iSize,iSize)
00027 {
00028     assert(iSize >= 2);
00029     m_iSize = iSize;
00030     m_afDiag = WM4_NEW Real[m_iSize];
00031     m_afSubd = WM4_NEW Real[m_iSize];
00032     m_bIsRotation = false;
00033 }
00034 //----------------------------------------------------------------------------
00035 template <class Real>
00036 Eigen<Real>::Eigen (const Matrix2<Real>& rkM)
00037     :
00038     m_kMat(2,2,(const Real*)rkM)
00039 {
00040     m_iSize = 2;
00041     m_afDiag = WM4_NEW Real[m_iSize];
00042     m_afSubd = WM4_NEW Real[m_iSize];
00043     m_bIsRotation = false;
00044 }
00045 //----------------------------------------------------------------------------
00046 template <class Real>
00047 Eigen<Real>::Eigen (const Matrix3<Real>& rkM)
00048     :
00049     m_kMat(3,3,(const Real*)rkM)
00050 {
00051     m_iSize = 3;
00052     m_afDiag = WM4_NEW Real[m_iSize];
00053     m_afSubd = WM4_NEW Real[m_iSize];
00054     m_bIsRotation = false;
00055 }
00056 //----------------------------------------------------------------------------
00057 template <class Real>
00058 Eigen<Real>::Eigen (const GMatrix<Real>& rkM)
00059     :
00060     m_kMat(rkM)
00061 {
00062     m_iSize = rkM.GetRows();
00063     assert(m_iSize >= 2 && (rkM.GetColumns() == m_iSize));
00064     m_afDiag = WM4_NEW Real[m_iSize];
00065     m_afSubd = WM4_NEW Real[m_iSize];
00066     m_bIsRotation = false;
00067 }
00068 //----------------------------------------------------------------------------
00069 template <class Real>
00070 Eigen<Real>::~Eigen ()
00071 {
00072     WM4_DELETE[] m_afSubd;
00073     WM4_DELETE[] m_afDiag;
00074 }
00075 //----------------------------------------------------------------------------
00076 template <class Real>
00077 Real& Eigen<Real>::operator() (int iRow, int iCol)
00078 {
00079     return m_kMat[iRow][iCol];
00080 }
00081 //----------------------------------------------------------------------------
00082 template <class Real>
00083 Eigen<Real>& Eigen<Real>::operator= (const Matrix2<Real>& rkM)
00084 {
00085     m_kMat.SetMatrix(2,2,(const Real*)rkM);
00086     m_iSize = 2;
00087     WM4_DELETE[] m_afDiag;
00088     WM4_DELETE[] m_afSubd;
00089     m_afDiag = WM4_NEW Real[m_iSize];
00090     m_afSubd = WM4_NEW Real[m_iSize];
00091     return *this;
00092 }
00093 //----------------------------------------------------------------------------
00094 template <class Real>
00095 Eigen<Real>& Eigen<Real>::operator= (const Matrix3<Real>& rkM)
00096 {
00097     m_kMat.SetMatrix(3,3,(const Real*)rkM);
00098     m_iSize = 3;
00099     WM4_DELETE[] m_afDiag;
00100     WM4_DELETE[] m_afSubd;
00101     m_afDiag = WM4_NEW Real[m_iSize];
00102     m_afSubd = WM4_NEW Real[m_iSize];
00103     return *this;
00104 }
00105 //----------------------------------------------------------------------------
00106 template <class Real>
00107 Eigen<Real>& Eigen<Real>::operator= (const GMatrix<Real>& rkM)
00108 {
00109     m_kMat = rkM;
00110     return *this;
00111 }
00112 //----------------------------------------------------------------------------
00113 template <class Real>
00114 Real Eigen<Real>::GetEigenvalue (int i) const
00115 {
00116     return m_afDiag[i];
00117 }
00118 //----------------------------------------------------------------------------
00119 template <class Real>
00120 const Real* Eigen<Real>::GetEigenvalues () const
00121 {
00122     return m_afDiag;
00123 }
00124 //----------------------------------------------------------------------------
00125 template <class Real>
00126 void Eigen<Real>::GetEigenvector (int i, Vector2<Real>& rkV) const
00127 {
00128     assert(m_iSize == 2);
00129     if (m_iSize == 2)
00130     {
00131         for (int iRow = 0; iRow < m_iSize; iRow++)
00132         {
00133             rkV[iRow] = m_kMat[iRow][i];
00134         }
00135     }
00136     else
00137     {
00138         rkV = Vector2<Real>::ZERO;
00139     }
00140 }
00141 //----------------------------------------------------------------------------
00142 template <class Real>
00143 void Eigen<Real>::GetEigenvector (int i, Vector3<Real>& rkV) const
00144 {
00145     assert(m_iSize == 3);
00146     if (m_iSize == 3)
00147     {
00148         for (int iRow = 0; iRow < m_iSize; iRow++)
00149         {
00150             rkV[iRow] = m_kMat[iRow][i];
00151         }
00152     }
00153     else
00154     {
00155         rkV = Vector3<Real>::ZERO;
00156     }
00157 }
00158 //----------------------------------------------------------------------------
00159 template <class Real>
00160 GVector<Real> Eigen<Real>::GetEigenvector (int i) const
00161 {
00162     return m_kMat.GetColumn(i);
00163 }
00164 //----------------------------------------------------------------------------
00165 template <class Real>
00166 const GMatrix<Real>& Eigen<Real>::GetEigenvectors () const
00167 {
00168     return m_kMat;
00169 }
00170 //----------------------------------------------------------------------------
00171 template <class Real>
00172 void Eigen<Real>::Tridiagonal2 ()
00173 {
00174     // matrix is already tridiagonal
00175     m_afDiag[0] = m_kMat[0][0];
00176     m_afDiag[1] = m_kMat[1][1];
00177     m_afSubd[0] = m_kMat[0][1];
00178     m_afSubd[1] = (Real)0.0;
00179     m_kMat[0][0] = (Real)1.0;
00180     m_kMat[0][1] = (Real)0.0;
00181     m_kMat[1][0] = (Real)0.0;
00182     m_kMat[1][1] = (Real)1.0;
00183 
00184     m_bIsRotation = true;
00185 }
00186 //----------------------------------------------------------------------------
00187 template <class Real>
00188 void Eigen<Real>::Tridiagonal3 ()
00189 {
00190     Real fM00 = m_kMat[0][0];
00191     Real fM01 = m_kMat[0][1];
00192     Real fM02 = m_kMat[0][2];
00193     Real fM11 = m_kMat[1][1];
00194     Real fM12 = m_kMat[1][2];
00195     Real fM22 = m_kMat[2][2];
00196 
00197     m_afDiag[0] = fM00;
00198     m_afSubd[2] = (Real)0.0;
00199     if (Math<Real>::FAbs(fM02) > Math<Real>::ZERO_TOLERANCE)
00200     {
00201         Real fLength = Math<Real>::Sqrt(fM01*fM01+fM02*fM02);
00202         Real fInvLength = ((Real)1.0)/fLength;
00203         fM01 *= fInvLength;
00204         fM02 *= fInvLength;
00205         Real fQ = ((Real)2.0)*fM01*fM12+fM02*(fM22-fM11);
00206         m_afDiag[1] = fM11+fM02*fQ;
00207         m_afDiag[2] = fM22-fM02*fQ;
00208         m_afSubd[0] = fLength;
00209         m_afSubd[1] = fM12-fM01*fQ;
00210         m_kMat[0][0] = (Real)1.0;
00211         m_kMat[0][1] = (Real)0.0;
00212         m_kMat[0][2] = (Real)0.0;
00213         m_kMat[1][0] = (Real)0.0;
00214         m_kMat[1][1] = fM01;
00215         m_kMat[1][2] = fM02;
00216         m_kMat[2][0] = (Real)0.0;
00217         m_kMat[2][1] = fM02;
00218         m_kMat[2][2] = -fM01;
00219         m_bIsRotation = false;
00220     }
00221     else
00222     {
00223         m_afDiag[1] = fM11;
00224         m_afDiag[2] = fM22;
00225         m_afSubd[0] = fM01;
00226         m_afSubd[1] = fM12;
00227         m_kMat[0][0] = (Real)1.0;
00228         m_kMat[0][1] = (Real)0.0;
00229         m_kMat[0][2] = (Real)0.0;
00230         m_kMat[1][0] = (Real)0.0;
00231         m_kMat[1][1] = (Real)1.0;
00232         m_kMat[1][2] = (Real)0.0;
00233         m_kMat[2][0] = (Real)0.0;
00234         m_kMat[2][1] = (Real)0.0;
00235         m_kMat[2][2] = (Real)1.0;
00236         m_bIsRotation = true;
00237     }
00238 }
00239 //----------------------------------------------------------------------------
00240 template <class Real>
00241 void Eigen<Real>::TridiagonalN ()
00242 {
00243     int i0, i1, i2, i3;
00244 
00245     for (i0 = m_iSize-1, i3 = m_iSize-2; i0 >= 1; i0--, i3--)
00246     {
00247         Real fH = (Real)0.0, fScale = (Real)0.0;
00248 
00249         if (i3 > 0)
00250         {
00251             for (i2 = 0; i2 <= i3; i2++)
00252             {
00253                 fScale += Math<Real>::FAbs(m_kMat[i0][i2]);
00254             }
00255             if (fScale == (Real)0.0)
00256             {
00257                 m_afSubd[i0] = m_kMat[i0][i3];
00258             }
00259             else
00260             {
00261                 Real fInvScale = ((Real)1.0)/fScale;
00262                 for (i2 = 0; i2 <= i3; i2++)
00263                 {
00264                     m_kMat[i0][i2] *= fInvScale;
00265                     fH += m_kMat[i0][i2]*m_kMat[i0][i2];
00266                 }
00267                 Real fF = m_kMat[i0][i3];
00268                 Real fG = Math<Real>::Sqrt(fH);
00269                 if (fF > (Real)0.0)
00270                 {
00271                     fG = -fG;
00272                 }
00273                 m_afSubd[i0] = fScale*fG;
00274                 fH -= fF*fG;
00275                 m_kMat[i0][i3] = fF-fG;
00276                 fF = (Real)0.0;
00277                 Real fInvH = ((Real)1.0)/fH;
00278                 for (i1 = 0; i1 <= i3; i1++)
00279                 {
00280                     m_kMat[i1][i0] = m_kMat[i0][i1]*fInvH;
00281                     fG = (Real)0.0;
00282                     for (i2 = 0; i2 <= i1; i2++)
00283                     {
00284                         fG += m_kMat[i1][i2]*m_kMat[i0][i2];
00285                     }
00286                     for (i2 = i1+1; i2 <= i3; i2++)
00287                     {
00288                         fG += m_kMat[i2][i1]*m_kMat[i0][i2];
00289                     }
00290                     m_afSubd[i1] = fG*fInvH;
00291                     fF += m_afSubd[i1]*m_kMat[i0][i1];
00292                 }
00293                 Real fHalfFdivH = ((Real)0.5)*fF*fInvH;
00294                 for (i1 = 0; i1 <= i3; i1++)
00295                 {
00296                     fF = m_kMat[i0][i1];
00297                     fG = m_afSubd[i1] - fHalfFdivH*fF;
00298                     m_afSubd[i1] = fG;
00299                     for (i2 = 0; i2 <= i1; i2++)
00300                     {
00301                         m_kMat[i1][i2] -= fF*m_afSubd[i2] +
00302                             fG*m_kMat[i0][i2];
00303                     }
00304                 }
00305             }
00306         }
00307         else
00308         {
00309             m_afSubd[i0] = m_kMat[i0][i3];
00310         }
00311 
00312         m_afDiag[i0] = fH;
00313     }
00314 
00315     m_afDiag[0] = (Real)0.0;
00316     m_afSubd[0] = (Real)0.0;
00317     for (i0 = 0, i3 = -1; i0 <= m_iSize-1; i0++, i3++)
00318     {
00319         if (m_afDiag[i0] != (Real)0.0)
00320         {
00321             for (i1 = 0; i1 <= i3; i1++)
00322             {
00323                 Real fSum = (Real)0.0;
00324                 for (i2 = 0; i2 <= i3; i2++)
00325                 {
00326                     fSum += m_kMat[i0][i2]*m_kMat[i2][i1];
00327                 }
00328                 for (i2 = 0; i2 <= i3; i2++)
00329                 {
00330                     m_kMat[i2][i1] -= fSum*m_kMat[i2][i0];
00331                 }
00332             }
00333         }
00334         m_afDiag[i0] = m_kMat[i0][i0];
00335         m_kMat[i0][i0] = (Real)1.0;
00336         for (i1 = 0; i1 <= i3; i1++)
00337         {
00338             m_kMat[i1][i0] = (Real)0.0;
00339             m_kMat[i0][i1] = (Real)0.0;
00340         }
00341     }
00342 
00343     // re-ordering if Eigen::QLAlgorithm is used subsequently
00344     for (i0 = 1, i3 = 0; i0 < m_iSize; i0++, i3++)
00345     {
00346         m_afSubd[i3] = m_afSubd[i0];
00347     }
00348     m_afSubd[m_iSize-1] = (Real)0.0;
00349 
00350     m_bIsRotation = ((m_iSize % 2) == 0);
00351 }
00352 //----------------------------------------------------------------------------
00353 template <class Real>
00354 bool Eigen<Real>::QLAlgorithm ()
00355 {
00356     const int iMaxIter = 32;
00357 
00358     for (int i0 = 0; i0 < m_iSize; i0++)
00359     {
00360         int i1;
00361         for (i1 = 0; i1 < iMaxIter; i1++)
00362         {
00363             int i2;
00364             for (i2 = i0; i2 <= m_iSize-2; i2++)
00365             {
00366                 Real fTmp = Math<Real>::FAbs(m_afDiag[i2]) +
00367                     Math<Real>::FAbs(m_afDiag[i2+1]);
00368 
00369                 if (Math<Real>::FAbs(m_afSubd[i2]) + fTmp == fTmp)
00370                 {
00371                     break;
00372                 }
00373             }
00374             if (i2 == i0)
00375             {
00376                 break;
00377             }
00378 
00379             Real fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((Real)2.0) *
00380                 m_afSubd[i0]);
00381             Real fR = Math<Real>::Sqrt(fG*fG+(Real)1.0);
00382             if ( fG < (Real)0.0 )
00383             {
00384                 fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
00385             }
00386             else
00387             {
00388                 fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
00389             }
00390             Real fSin = (Real)1.0, fCos = (Real)1.0, fP = (Real)0.0;
00391             for (int i3 = i2-1; i3 >= i0; i3--)
00392             {
00393                 Real fF = fSin*m_afSubd[i3];
00394                 Real fB = fCos*m_afSubd[i3];
00395                 if (Math<Real>::FAbs(fF) >= Math<Real>::FAbs(fG))
00396                 {
00397                     fCos = fG/fF;
00398                     fR = Math<Real>::Sqrt(fCos*fCos+(Real)1.0);
00399                     m_afSubd[i3+1] = fF*fR;
00400                     fSin = ((Real)1.0)/fR;
00401                     fCos *= fSin;
00402                 }
00403                 else
00404                 {
00405                     fSin = fF/fG;
00406                     fR = Math<Real>::Sqrt(fSin*fSin+(Real)1.0);
00407                     m_afSubd[i3+1] = fG*fR;
00408                     fCos = ((Real)1.0)/fR;
00409                     fSin *= fCos;
00410                 }
00411                 fG = m_afDiag[i3+1]-fP;
00412                 fR = (m_afDiag[i3]-fG)*fSin+((Real)2.0)*fB*fCos;
00413                 fP = fSin*fR;
00414                 m_afDiag[i3+1] = fG+fP;
00415                 fG = fCos*fR-fB;
00416 
00417                 for (int i4 = 0; i4 < m_iSize; i4++)
00418                 {
00419                     fF = m_kMat[i4][i3+1];
00420                     m_kMat[i4][i3+1] = fSin*m_kMat[i4][i3]+fCos*fF;
00421                     m_kMat[i4][i3] = fCos*m_kMat[i4][i3]-fSin*fF;
00422                 }
00423             }
00424             m_afDiag[i0] -= fP;
00425             m_afSubd[i0] = fG;
00426             m_afSubd[i2] = (Real)0.0;
00427         }
00428         if (i1 == iMaxIter)
00429         {
00430             return false;
00431         }
00432     }
00433 
00434     return true;
00435 }
00436 //----------------------------------------------------------------------------
00437 template <class Real>
00438 void Eigen<Real>::DecreasingSort ()
00439 {
00440     // sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
00441     for (int i0 = 0, i1; i0 <= m_iSize-2; i0++)
00442     {
00443         // locate maximum eigenvalue
00444         i1 = i0;
00445         Real fMax = m_afDiag[i1];
00446         int i2;
00447         for (i2 = i0+1; i2 < m_iSize; i2++)
00448         {
00449             if (m_afDiag[i2] > fMax)
00450             {
00451                 i1 = i2;
00452                 fMax = m_afDiag[i1];
00453             }
00454         }
00455 
00456         if (i1 != i0)
00457         {
00458             // swap eigenvalues
00459             m_afDiag[i1] = m_afDiag[i0];
00460             m_afDiag[i0] = fMax;
00461 
00462             // swap eigenvectors
00463             for (i2 = 0; i2 < m_iSize; i2++)
00464             {
00465                 Real fTmp = m_kMat[i2][i0];
00466                 m_kMat[i2][i0] = m_kMat[i2][i1];
00467                 m_kMat[i2][i1] = fTmp;
00468                 m_bIsRotation = !m_bIsRotation;
00469             }
00470         }
00471     }
00472 }
00473 //----------------------------------------------------------------------------
00474 template <class Real>
00475 void Eigen<Real>::IncreasingSort ()
00476 {
00477     // sort eigenvalues in increasing order, e[0] <= ... <= e[iSize-1]
00478     for (int i0 = 0, i1; i0 <= m_iSize-2; i0++)
00479     {
00480         // locate minimum eigenvalue
00481         i1 = i0;
00482         Real fMin = m_afDiag[i1];
00483         int i2;
00484         for (i2 = i0+1; i2 < m_iSize; i2++)
00485         {
00486             if (m_afDiag[i2] < fMin)
00487             {
00488                 i1 = i2;
00489                 fMin = m_afDiag[i1];
00490             }
00491         }
00492 
00493         if (i1 != i0)
00494         {
00495             // swap eigenvalues
00496             m_afDiag[i1] = m_afDiag[i0];
00497             m_afDiag[i0] = fMin;
00498 
00499             // swap eigenvectors
00500             for (i2 = 0; i2 < m_iSize; i2++)
00501             {
00502                 Real fTmp = m_kMat[i2][i0];
00503                 m_kMat[i2][i0] = m_kMat[i2][i1];
00504                 m_kMat[i2][i1] = fTmp;
00505                 m_bIsRotation = !m_bIsRotation;
00506             }
00507         }
00508     }
00509 }
00510 //----------------------------------------------------------------------------
00511 template <class Real>
00512 void Eigen<Real>::GuaranteeRotation ()
00513 {
00514     if (!m_bIsRotation)
00515     {
00516         // change sign on the first column
00517         for (int iRow = 0; iRow < m_iSize; iRow++)
00518         {
00519             m_kMat[iRow][0] = -m_kMat[iRow][0];
00520         }
00521     }
00522 }
00523 //----------------------------------------------------------------------------
00524 template <class Real>
00525 void Eigen<Real>::EigenStuff2 ()
00526 {
00527     Tridiagonal2();
00528     QLAlgorithm();
00529     GuaranteeRotation();
00530 }
00531 //----------------------------------------------------------------------------
00532 template <class Real>
00533 void Eigen<Real>::EigenStuff3 ()
00534 {
00535     Tridiagonal3();
00536     QLAlgorithm();
00537     GuaranteeRotation();
00538 }
00539 //----------------------------------------------------------------------------
00540 template <class Real>
00541 void Eigen<Real>::EigenStuffN ()
00542 {
00543     TridiagonalN();
00544     QLAlgorithm();
00545     GuaranteeRotation();
00546 }
00547 //----------------------------------------------------------------------------
00548 template <class Real>
00549 void Eigen<Real>::EigenStuff ()
00550 {
00551     switch (m_iSize)
00552     {
00553         case 2:  Tridiagonal2();  break;
00554         case 3:  Tridiagonal3();  break;
00555         default: TridiagonalN();  break;
00556     }
00557     QLAlgorithm();
00558     GuaranteeRotation();
00559 }
00560 //----------------------------------------------------------------------------
00561 template <class Real>
00562 void Eigen<Real>::DecrSortEigenStuff2 ()
00563 {
00564     Tridiagonal2();
00565     QLAlgorithm();
00566     DecreasingSort();
00567     GuaranteeRotation();
00568 }
00569 //----------------------------------------------------------------------------
00570 template <class Real>
00571 void Eigen<Real>::DecrSortEigenStuff3 ()
00572 {
00573     Tridiagonal3();
00574     QLAlgorithm();
00575     DecreasingSort();
00576     GuaranteeRotation();
00577 }
00578 //----------------------------------------------------------------------------
00579 template <class Real>
00580 void Eigen<Real>::DecrSortEigenStuffN ()
00581 {
00582     TridiagonalN();
00583     QLAlgorithm();
00584     DecreasingSort();
00585     GuaranteeRotation();
00586 }
00587 //----------------------------------------------------------------------------
00588 template <class Real>
00589 void Eigen<Real>::DecrSortEigenStuff ()
00590 {
00591     switch (m_iSize)
00592     {
00593         case 2:  Tridiagonal2();  break;
00594         case 3:  Tridiagonal3();  break;
00595         default: TridiagonalN();  break;
00596     }
00597     QLAlgorithm();
00598     DecreasingSort();
00599     GuaranteeRotation();
00600 }
00601 //----------------------------------------------------------------------------
00602 template <class Real>
00603 void Eigen<Real>::IncrSortEigenStuff2 ()
00604 {
00605     Tridiagonal2();
00606     QLAlgorithm();
00607     IncreasingSort();
00608     GuaranteeRotation();
00609 }
00610 //----------------------------------------------------------------------------
00611 template <class Real>
00612 void Eigen<Real>::IncrSortEigenStuff3 ()
00613 {
00614     Tridiagonal3();
00615     QLAlgorithm();
00616     IncreasingSort();
00617     GuaranteeRotation();
00618 }
00619 //----------------------------------------------------------------------------
00620 template <class Real>
00621 void Eigen<Real>::IncrSortEigenStuffN ()
00622 {
00623     TridiagonalN();
00624     QLAlgorithm();
00625     IncreasingSort();
00626     GuaranteeRotation();
00627 }
00628 //----------------------------------------------------------------------------
00629 template <class Real>
00630 void Eigen<Real>::IncrSortEigenStuff ()
00631 {
00632     switch (m_iSize)
00633     {
00634         case 2:  Tridiagonal2();  break;
00635         case 3:  Tridiagonal3();  break;
00636         default: TridiagonalN();  break;
00637     }
00638     QLAlgorithm();
00639     IncreasingSort();
00640     GuaranteeRotation();
00641 }
00642 //----------------------------------------------------------------------------
00643 
00644 //----------------------------------------------------------------------------
00645 // explicit instantiation
00646 //----------------------------------------------------------------------------
00647 template WM4_FOUNDATION_ITEM
00648 class Eigen<float>;
00649 
00650 template WM4_FOUNDATION_ITEM
00651 class Eigen<double>;
00652 //----------------------------------------------------------------------------
00653 }

Generated on Wed Nov 23 19:01:03 2011 for FreeCAD by  doxygen 1.6.1