vector_math.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:10k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: vector_math.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:29:54  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: vector_math.cpp,v 1000.2 2004/06/01 18:29:54 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Authors:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      Vector and Matrix classes to simplify 3-d geometry calculations
  38. *
  39. * ===========================================================================
  40. */
  41. #ifdef _MSC_VER
  42. #pragma warning(disable:4018)   // disable signed/unsigned mismatch warning in MSVC
  43. #endif
  44. #include <ncbi_pch.hpp>
  45. #include "vector_math.hpp"
  46. BEGIN_SCOPE(Cn3D)
  47. void SetTranslationMatrix(Matrix* m, const Vector& v, int n)
  48. {
  49.     m->m[0]=1;  m->m[1]=0;  m->m[2]=0;  m->m[3]=n*v.x;
  50.     m->m[4]=0;  m->m[5]=1;  m->m[6]=0;  m->m[7]=n*v.y;
  51.     m->m[8]=0;  m->m[9]=0;  m->m[10]=1; m->m[11]=n*v.z;
  52.     m->m[12]=0; m->m[13]=0; m->m[14]=0; m->m[15]=1;
  53. }
  54. void SetScaleMatrix(Matrix* m, const Vector& v)
  55. {
  56.     m->m[0]=v.x; m->m[1]=0;   m->m[2]=0;    m->m[3]=0;
  57.     m->m[4]=0;   m->m[5]=v.y; m->m[6]=0;    m->m[7]=0;
  58.     m->m[8]=0;   m->m[9]=0;   m->m[10]=v.z; m->m[11]=0;
  59.     m->m[12]=0;  m->m[13]=0;  m->m[14]=0;   m->m[15]=1;
  60.     return;
  61. }
  62. void SetRotationMatrix(Matrix* m, const Vector& v, double rad, int n)
  63. {
  64.     double c, s, t;
  65.     Vector u(v);
  66.     u.normalize();
  67.     c=cos(n*rad);
  68.     s=sin(n*rad);
  69.     t=1.0-c;
  70.     m->m[0]=u.x*u.x*t+c;
  71.     m->m[1]=u.x*u.y*t-u.z*s;
  72.     m->m[2]=u.x*u.z*t+u.y*s;
  73.     m->m[3]=0;
  74.     m->m[4]=u.x*u.y*t+u.z*s;
  75.     m->m[5]=u.y*u.y*t+c;
  76.     m->m[6]=u.y*u.z*t-u.x*s;
  77.     m->m[7]=0;
  78.     m->m[8]=u.x*u.z*t-u.y*s;
  79.     m->m[9]=u.y*u.z*t+u.x*s;
  80.     m->m[10]=u.z*u.z*t+c;
  81.     m->m[11]=0;
  82.     m->m[12]=m->m[13]=m->m[14]=0; m->m[15]=1;
  83.     return;
  84. }
  85. void ApplyTransformation(Vector* v, const Matrix& m)
  86. {
  87.     Vector t;
  88.     t.x=m.m[0]*v->x + m.m[1]*v->y + m.m[2]*v->z  + m.m[3];
  89.     t.y=m.m[4]*v->x + m.m[5]*v->y + m.m[6]*v->z  + m.m[7];
  90.     t.z=m.m[8]*v->x + m.m[9]*v->y + m.m[10]*v->z + m.m[11];
  91.     *v = t;
  92.     return;
  93. }
  94. // C = A x B
  95. void ComposeInto(Matrix* C, const Matrix& A, const Matrix& B)
  96. {
  97.     for (int i=0; i<4; ++i) {
  98.         for (int j=0; j<4; ++j) {
  99.             C->m[4*i+j]=0;
  100.             for (int s=0; s<4; ++s) {
  101.                 C->m[4*i+j] += (A.m[4*i+s])*(B.m[4*s+j]);
  102.             }
  103.         }
  104.     }
  105.     return;
  106. }
  107. //
  108. // The following inverts a 4x4 matrix whose bottom row is { 0 0 0 1 } - i.e.
  109. // a matrix composed only of rotate, scale, and translate matrixes.
  110. //
  111. void InvertInto(Matrix* I, const Matrix& A)
  112. {
  113.     const double&
  114.         a=A.m[0], b=A.m[1], c=A.m[2], d=A.m[3],
  115.         e=A.m[4], f=A.m[5], g=A.m[6], h=A.m[7],
  116.         i=A.m[8], j=A.m[9], k=A.m[10], l=A.m[11];
  117.     double denom=(-(c*f*i) + b*g*i + c*e*j - a*g*j - b*e*k + a*f*k);
  118.     I->m[0]= (-(g*j) + f*k)/denom;
  119.     I->m[1]= (c*j - b*k)/denom;
  120.     I->m[2]= (-(c*f) + b*g)/denom;
  121.     I->m[3]= (d*g*j - c*h*j - d*f*k + b*h*k + c*f*l - b*g*l)/denom;
  122.     I->m[4]= (g*i - e*k)/denom;
  123.     I->m[5]= (-(c*i) + a*k)/denom;
  124.     I->m[6]= (c*e - a*g)/denom;
  125.     I->m[7]= (-(d*g*i) + c*h*i + d*e*k - a*h*k - c*e*l + a*g*l)/denom;
  126.     I->m[8]= (-(f*i) + e*j)/denom;
  127.     I->m[9]= (b*i - a*j)/denom;
  128.     I->m[10]= (-(b*e) + a*f)/denom;
  129.     I->m[11]= (d*f*i - b*h*i - d*e*j + a*h*j + b*e*l - a*f*l)/denom;
  130.     I->m[12]=0; I->m[13]=0; I->m[14]=0; I->m[15]=1;
  131.     return;
  132. }
  133. //---------------------------------------------------------------------
  134. // copied from:  /PROGRAMS/SigmaX2.2/SIGLIB/RigidBody.c
  135. //
  136. //    S*I*G*M*A - 1996 program
  137. // revised 1996        J. Hermans, Univ. N. Carolina
  138. //
  139. //     perform rigid body fit for two structures
  140. //         (cf. Ferro&Hermans and McLachlan)
  141. //
  142. // inputs:
  143. //    natx:          number of atoms
  144. //    xref:          reference coordinates
  145. //    xvar:          variable coordinates
  146. //    Inverse_mass:  inverse weights (1 per atom)
  147. //    do_select:     use the Selection array
  148. //    selected:      selection array
  149. //
  150. // outputs:
  151. //    cgref:     c.o.mass of xref
  152. //    cgvar:     c.o.mass of xvar
  153. //
  154. //  NEW xvar = cgref + rot * ( OLD xvar - cgvar ).
  155. //  The new xvar will be the best approximation to xref.
  156. //---------------------------------------------------------------------
  157. // Adapted for Cn3D++ with Vector, Matrix classes by Paul Thiessen.
  158. // xvar Vectors are left unchanged; instead, the transformations necessary
  159. // to superimpose the variable structure onto the reference structure
  160. // are returned in cgref, cgvar, and rotMat. The transformation process is:
  161. // 1) translate variable so its center of mass is at origin; 2) apply
  162. // rotation in rotMat; 3) translate variable so its center of mass is
  163. // at center of mass of reference.
  164. void RigidBodyFit(
  165.     int natx, const Vector * const *xref, const Vector * const *xvar, const double *weights,
  166.     Vector& cgref, Vector& cgvar, Matrix& rotMat)
  167. {
  168.     Vector  t, phi, cosin, sine;
  169.     double  rot[3][3], corlnmatrx[3][3];
  170.     int     flag1, flag2, flag3;
  171.     int     i, j, iatv, ix;
  172.     double  an2, xx, f, fz, sgn, del, phix, phibes;
  173.     double  tol = .0001;
  174.     // compute centroids
  175.     cgref *= 0;
  176.     cgvar *= 0;
  177.     an2 = 0.;
  178.     for (iatv=0; iatv<natx; ++iatv) {
  179.         if (weights[iatv] <= 0.) continue;
  180.         an2 += weights[iatv];
  181.         cgref += *(xref[iatv]) * weights[iatv];
  182.         cgvar += *(xvar[iatv]) * weights[iatv];
  183.     }
  184.     cgref /= an2;
  185.     cgvar /= an2;
  186.     // compute correlation matrix
  187.     for (i=0; i<3; ++i) {
  188.         cosin[i] = 1.;
  189.         for (j=0; j<3; ++j) {
  190.             corlnmatrx[i][j] = 0.;
  191.         }
  192.     }
  193.     for (iatv=0; iatv<natx; ++iatv) {
  194.         for (i=0; i<3; ++i) {
  195.             if (weights[iatv] <= 0.) continue;
  196.             xx = ((*(xvar[iatv]))[i] - cgvar[i]) * weights[iatv];
  197.             for (j=0; j<3; ++j) {
  198.                 corlnmatrx[i][j] += xx * ((*(xref[iatv]))[j] - cgref[j]);
  199.             }
  200.         }
  201.     }
  202.     // evaluate rotation matrix iteratively
  203.     flag1 = flag2 = flag3 = false;
  204.     ix = 0;
  205.     del = .5;
  206.     sgn = 1.;
  207.     phibes = phix = 0.;
  208.     while (true) {
  209.         cosin[ix] = cos(phix);
  210.         sine[ix] = sin(phix);
  211.         rot[0][0] = cosin[1] * cosin[2];
  212.         rot[1][0] = cosin[1] * sine[2];
  213.         rot[0][1] = sine[0] * sine[1] * cosin[2] - cosin[0] * sine[2];
  214.         rot[1][1] = sine[0] * sine[1] * sine[2] + cosin[0] * cosin[2];
  215.         rot[2][0] = -sine[1];
  216.         rot[2][1] = sine[0] * cosin[1];
  217.         rot[2][2] = cosin[0] * cosin[1];
  218.         rot[0][2] = cosin[0] * sine[1] * cosin[2] + sine[0] * sine[2];
  219.         rot[1][2] = cosin[0] * sine[1] * sine[2] - sine[0] * cosin[2];
  220.         // compute the trace of (rot x corlnmatrix)
  221.         f = 0.;
  222.         for (i=0; i<3; ++i) {
  223.             for (j=0; j<3; ++j) {
  224.                 f += rot[i][j] * corlnmatrx[i][j];
  225.             }
  226.         }
  227.         if (!flag3) {
  228.             fz = f;
  229.             flag3 = true;
  230.             phix = phibes + sgn * del;
  231.             phi[ix] = phix;
  232.             continue;
  233.         }
  234.         if (f > fz) {
  235.             // f went down, try again with same difference.
  236.             fz = f;
  237.             flag1 = true;
  238.             phibes = phi[ix];
  239.             flag2 = false;
  240.             phix = phibes + sgn * del;
  241.             phi[ix] = phix;
  242.             continue;
  243.         }
  244.         if (!flag1) {
  245.             // try in the opposite direction
  246.             sgn = -sgn;
  247.             flag1 = true;
  248.             phix = phibes + sgn * del;
  249.             phi[ix] = phix;
  250.             continue;
  251.         }
  252.         phi[ix] = phibes;
  253.         cosin[ix] = cos(phibes);
  254.         sine[ix] = sin(phibes);
  255.         flag1 = false;
  256.         if (ix < 2) {
  257.             // apply the same del to the next Euler angle
  258.             ++ix;
  259.             phibes = phi[ix];
  260.             phi[ix] = phix = phibes + sgn * del;
  261.             continue;
  262.         }
  263.         if (flag2) {
  264.             // cut del in half
  265.             flag2 = false;
  266.             del *= .5;
  267.             if (del < tol) break;
  268.         } else {
  269.             flag2 = true;
  270.         }
  271.         ix = 0;
  272.         phibes = phi[ix];
  273.         phix = phibes + sgn * del;
  274.         phi[ix] = phix;
  275.     }
  276.     // end iterative evaluation of rotation matrix
  277.     // store computed rotation matrix in rotMat
  278.     rotMat.SetToIdentity();
  279.     for (i=0; i<3; ++i) {
  280.         for (j=0; j<3; ++j) {
  281.             rotMat[4*i + j] = rot[j][i];
  282.         }
  283.     }
  284. } // end RigidBodyFit()
  285. END_SCOPE(Cn3D)
  286. /*
  287. * ---------------------------------------------------------------------------
  288. * $Log: vector_math.cpp,v $
  289. * Revision 1000.2  2004/06/01 18:29:54  gouriano
  290. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  291. *
  292. * Revision 1.8  2004/05/21 21:41:40  gorelenk
  293. * Added PCH ncbi_pch.hpp
  294. *
  295. * Revision 1.7  2004/03/15 18:38:52  thiessen
  296. * prefer prefix vs. postfix ++/-- operators
  297. *
  298. * Revision 1.6  2004/02/19 17:05:22  thiessen
  299. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  300. *
  301. * Revision 1.5  2003/02/03 19:20:08  thiessen
  302. * format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros
  303. *
  304. * Revision 1.4  2001/02/09 20:17:32  thiessen
  305. * ignore atoms w/o alpha when doing structure realignment
  306. *
  307. * Revision 1.3  2000/11/13 18:06:53  thiessen
  308. * working structure re-superpositioning
  309. *
  310. * Revision 1.2  2000/07/17 22:37:18  thiessen
  311. * fix vector_math typo; correctly set initial view
  312. *
  313. * Revision 1.1  2000/06/27 20:09:41  thiessen
  314. * initial checkin
  315. *
  316. */