transform.c

来自「最经典的分子对结软件」· C语言 代码 · 共 579 行

C
579
字号
/*                                                                    *//*                        Copyright UCSF, 1997                        *//*                                                                    *//*Written by Todd Ewing10/95*/#include "define.h"#include "utility.h"#include "mol.h"#include "global.h"#include "vector.h"#include "transform.h"/* ///////////////////////////////////////////////////////////// */int orient_molecule(  MOLECULE *target,  MOLECULE *current,  MOLECULE *mol_ref,  MOLECULE *mol_conf,  MOLECULE *mol_ori){  static XYZ rotation_matrix[3];/** Calculate rotation matrix and translation vector.* 6/95 te*/  if (!orient_gk_  (    &target->total.atoms,    target->coord,    current->coord,    mol_ori->transform.com,    rotation_matrix,    mol_ori->transform.translate,    &mol_ori->transform.refl_flag  ))    return FALSE;/** Update transform records* 10/96 te*/  get_quaternion_from_matrix  (    mol_ori->transform.rotate,    &mol_ori->transform.refl_flag,    rotation_matrix  );  mol_ori->transform.trans_flag = TRUE;  mol_ori->transform.rot_flag = TRUE;/** If a previous transformation is present, then update this info* 10/96 te*/  if (mol_conf->transform.rot_flag)    overall_rotation (mol_ori, mol_conf);  if (mol_conf->transform.trans_flag)    overall_translation (mol_ori, mol_conf);/** Transform the molecule coordinates* 10/96 te*/  transform_molecule (mol_ori, mol_ref);  return TRUE;}/* ///////////////////////////////////////////////////////////// */void transform_molecule(  MOLECULE *mol_trans,  MOLECULE *mol_ref){  int i;  mol_trans->transform.flag = TRUE;/** Perform a rigid-body rotation/translation* 12/96 te*/  if ((mol_trans->transform.trans_flag == TRUE) ||    (mol_trans->transform.rot_flag == TRUE))    rigid_transform (mol_trans, mol_ref);/** Perform a rotation about each rotatable bond vector* 12/96 te*/  if (mol_trans->transform.tors_flag == TRUE)    for (i = 0; i < mol_trans->total.torsions; i++)      torsion_transform (mol_trans, i);}/* ///////////////////////////////////////////////////////////// */void rigid_transform(  MOLECULE *mol_trans,  MOLECULE *mol_ref){  static XYZ rotation[3];  mol_trans->transform.flag = TRUE;/** Calculate a rotation matrix from the quaternion* 12/96 te*/  get_matrix_from_quaternion  (    rotation,    mol_trans->transform.rotate,    mol_trans->transform.refl_flag  );  transform_  (    &mol_trans->total.atoms,    mol_ref->coord,    mol_trans->transform.com,    rotation,    mol_trans->transform.translate,    mol_trans->coord  );}/* ///////////////////////////////////////////////////////////// */void torsion_transform(  MOLECULE	*molecule,  int		torsion_id){  int i;  static XYZ bond_matrix[3];  static XYZ bond_vector;  static float difference;  void rotateaxis (float, XYZ, XYZ *);  molecule->transform.flag = TRUE;/** Compute current torsion angle and difference* 12/96 te*/  molecule->torsion[torsion_id].current_angle =    compute_torsion (molecule, torsion_id);  difference =    molecule->torsion[torsion_id].target_angle -    molecule->torsion[torsion_id].current_angle;/** If difference is significant, then rotate bond* 12/96 te*/  if (NON_ZERO (difference))  {    for (i = 0; i < 3; i++)      bond_vector[i] =        molecule->coord[molecule->torsion[torsion_id].target][i] -        molecule->coord[molecule->torsion[torsion_id].origin][i];    rotateaxis (difference, bond_vector, bond_matrix);    rotate_atoms    (      molecule,      bond_matrix,      molecule->torsion[torsion_id].target,      molecule->torsion[torsion_id].target    );    molecule->torsion[torsion_id].current_angle =      molecule->torsion[torsion_id].target_angle;  }}/* //////////////////////////////////////////////////////////////////////Subroutine that calculate a rotation matrix, given a vector axisand an angle of rotation.10/95 ys////////////////////////////////////////////////////////////////////// */void rotateaxis (float phi, XYZ vect, XYZ rot[3]){  float del1,del2,del3;  float vect_length;  float vcosx,vcosy,vcosz;  del1=1-cos(phi);  del2=sin(phi);  del3=cos(phi);  vect_length=sqrt(vect[0]*vect[0]+                   vect[1]*vect[1]+                   vect[2]*vect[2]);  vcosx= vect[0]/vect_length;  vcosy= vect[1]/vect_length;  vcosz= vect[2]/vect_length;  rot[0][0]=vcosx*vcosx*del1 + del3;  rot[0][1]=vcosx*vcosy*del1 + vcosz*del2;  rot[0][2]=vcosx*vcosz*del1 - vcosy*del2;  rot[1][0]=vcosy*vcosx*del1 - vcosz*del2;  rot[1][1]=vcosy*vcosy*del1 + del3;  rot[1][2]=vcosy*vcosz*del1 + vcosx*del2;  rot[2][0]=vcosz*vcosx*del1 + vcosy*del2;  rot[2][1]=vcosz*vcosy*del1 - vcosx*del2;  rot[2][2]=vcosz*vcosz*del1 + del3;  return;}/* /////////////////////////////////////////////////////////////////// */void rotate_atoms(  MOLECULE	*molecule,  XYZ		bond_matrix[3],  int		origin,  int		atom){  int i;/*  fprintf (global.outfile, "orig %s atom %s\n",    molecule->atom[origin].name,    molecule->atom[atom].name);*/  transform_atom_  (    molecule->coord[atom],    bond_matrix,    molecule->coord[origin]  );  for (i = 0; i < molecule->atom[atom].neighbor_total; i++)    if (molecule->atom[atom].neighbor[i].out_flag == TRUE)      rotate_atoms        (molecule, bond_matrix, origin, molecule->atom[atom].neighbor[i].id);}/* /////////////////////////////////////////////////////////////////// *//*Function to compute a rotation matrix from quaternion values.For discussion of this technique, see "Computer Simulation of Liquids"by M.P. Allen and D.J. Tildesley from Oxford Science Publishers, 198710/96 te*/int get_matrix_from_quaternion(  XYZ	m[3],		/* rotation matrix */  XYZ	qin,		/* input independent quaternion elements */  int	refl		/* reflection flag */){  int	i;		/* iterater */  float	qn;		/* dependent quaternion element, q-naught */  float	qn2;		/* square of q-naught */  XYZ	q;		/* independent quaternion elements */  XYZ	q2;		/* square of independent quaternion elements */  float	sum2;		/* sum of squares of independent q values */  float	sum;		/* sum of independent q values *//** Check that each q-value is between -1.0 and 1.0.* If not, remap into this range using wrap-around.* Compute q-squared values and their sum* 10/96 te*/  for (i = 0, sum2 = 0.0; i < 3; i++)  {    q[i] = qin[i];    if (q[i] > 1.0)      q[i] = fmod (q[i] + 1.0, 2.0) - 1.0;    else if (q[i] < -1.0)      q[i] = fmod (q[i] - 1.0, 2.0) + 1.0;    sum2 += q2[i] = SQR (q[i]);  }/** If the sum-of-squares is less than 1.0, compute q-naught* 10/96 te*/  if (sum2 < 1.0)  {    qn2 = 1.0 - sum2;    qn = sqrt (qn2);  }/** If the sum is 1.0, set q-naught to zero* 10/96 te*/  else if (sum2 == 1.0)    qn = qn2 = 0.0;/** Otherwise, renormalize q-values and set q-naught to zero* 10/96 te*/  else  {    for (i = 0; i < 3; i++)      q2[i] /= sum2;    for (i = 0, sum = sqrt (sum2); i < 3; i++)      q[i] /= sum;    qn = qn2 = 0.0;  }/** Compute rotation matrix elements* 10/96 te*/  m[0][0] = qn2 + q2[0] - q2[1] - q2[2];  m[0][1] = 2.0 * (q[0] * q[1] + qn * q[2]);  m[0][2] = 2.0 * (q[0] * q[2] - qn * q[1]);  m[1][0] = 2.0 * (q[0] * q[1] - qn * q[2]);  m[1][1] = qn2 - q2[0] + q2[1] - q2[2];  m[1][2] = 2.0 * (q[1] * q[2] + qn * q[0]);  m[2][0] = 2.0 * (q[0] * q[2] + qn * q[1]);  m[2][1] = 2.0 * (q[1] * q[2] - qn * q[0]);  m[2][2] = qn2 - q2[0] - q2[1] + q2[2];/** If a reflection is required, then update the matrix* 10/96 te*/  if (refl == TRUE)    for (i = 0; i < 3; i++)      m[i][2] *= -1.0;  return TRUE;}/* /////////////////////////////////////////////////////////////////// *//*Function to compute the quaternion values from a rotation matrixFor discussion of this technique, see "Computer Simulation of Liquids"by M.P. Allen and D.J. Tildesley from Oxford Science Publishers, 198710/96 te*/int get_quaternion_from_matrix(  XYZ	q,		/* independent quaternion elements */  int	*refl,		/* reflection flag */  XYZ	m[3]		/* rotation matrix */){  int	i;		/* iterater */  int	max;		/* quaternion element with greatest magnitude */  float	max_val;	/* value of greatest quaternion element */  float	qn;		/* dependent quaternion element, q-naught */  float	qn2;		/* square of q-naught */  XYZ	q2;		/* square of independent quaternion elements */  float	det;		/* determinant of input matrix *//** Compute determinant of matrix* 10/96 te*/  det =    m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) -    m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2]) +    m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]);/** If the determinant is negative, then set the reflection flag and* invert matrix* 10/96 te*/  if (det < 0.0)  {    *refl = TRUE;    for (i = 0; i < 3; i++)      m[i][2] *= -1.0;  }  else if (*refl != NEITHER)    *refl = FALSE;/** Calculate q-squared values (times 4)* 10/96 te*/  qn2   = 1.0 + m[0][0] + m[1][1] + m[2][2];  q2[0] = 1.0 + m[0][0] - m[1][1] - m[2][2];  q2[1] = 1.0 - m[0][0] + m[1][1] - m[2][2];  q2[2] = 1.0 - m[0][0] - m[1][1] + m[2][2];/** Identify the largest q-squared value* 10/96 te*/  for (i = max = 0, max_val = qn2; i < 3; i++)    if (q2[i] > max_val)    {      max_val = q2[i];      max = i + 1;    }/** Compute the other q-values based on the positive root* of the largest q-squared value* 10/96 te*/  switch (max)  {    case 0:    {      qn   = 0.5 * sqrt (qn2);      q[0] = 0.25 * (m[1][2] - m[2][1]) / qn;      q[1] = 0.25 * (m[2][0] - m[0][2]) / qn;      q[2] = 0.25 * (m[0][1] - m[1][0]) / qn;      break;    }    case 1:    {      q[0] = 0.5 * sqrt (q2[0]);      qn   = 0.25 * (m[1][2] - m[2][1]) / q[0];      q[1] = 0.25 * (m[0][1] + m[1][0]) / q[0];      q[2] = 0.25 * (m[0][2] + m[2][0]) / q[0];      break;    }    case 2:    {      q[1] = 0.5 * sqrt (q2[1]);      qn   = 0.25 * (m[2][0] - m[0][2]) / q[1];      q[0] = 0.25 * (m[1][0] + m[0][1]) / q[1];      q[2] = 0.25 * (m[2][1] + m[1][2]) / q[1];      break;    }    case 3:    {      q[2] = 0.5 * sqrt (q2[2]);      qn   = 0.25 * (m[0][1] - m[1][0]) / q[2];      q[0] = 0.25 * (m[2][0] + m[0][2]) / q[2];      q[1] = 0.25 * (m[2][1] + m[1][2]) / q[2];      break;    }    default:    {      printf ("Unable to find q2 value > 0\n");      return FALSE;    }  }/** Reset q-values so that q-naught is always positive* 10/96 te*/  if (qn < 0.0)    for (i = 0; i < 3; i++)      q[i] *= -1.0;  return TRUE;}/* /////////////////////////////////////////////////////////////////Compute current angle of specified bond10/96 te///////////////////////////////////////////////////////////////// */float compute_torsion (MOLECULE *molecule, int torsion_id){  if  (    (molecule->torsion[torsion_id].origin_neighbor == NEITHER) ||    (molecule->torsion[torsion_id].origin == NEITHER) ||    (molecule->torsion[torsion_id].target == NEITHER) ||    (molecule->torsion[torsion_id].target_neighbor == NEITHER)  )    exit (fprintf (global.outfile,      "ERROR compute_torsion: Torsion atoms undefined in %s\n",      molecule->info.name));  return    dihed    (      molecule->coord[molecule->torsion[torsion_id].origin_neighbor],      molecule->coord[molecule->torsion[torsion_id].origin],      molecule->coord[molecule->torsion[torsion_id].target],      molecule->coord[molecule->torsion[torsion_id].target_neighbor]    );}/* /////////////////////////////////////////////////////////////////Compute a new overall rotation10/96 te////////////////////////////////////////////////////////////////// */void overall_rotation(  MOLECULE *mol_new,  MOLECULE *mol_orig){  static XYZ rot_orig[3], rot_new[3], rot_temp[3];  get_matrix_from_quaternion    (rot_orig, mol_orig->transform.rotate, mol_orig->transform.refl_flag);  get_matrix_from_quaternion    (rot_new, mol_new->transform.rotate, mol_new->transform.refl_flag);  mmult3 (rot_orig, rot_new, rot_temp);  get_quaternion_from_matrix    (mol_new->transform.rotate, &mol_new->transform.refl_flag, rot_temp);}/* /////////////////////////////////////////////////////////////////Compute a new overall translation10/96 te////////////////////////////////////////////////////////////////// */void overall_translation(  MOLECULE *mol_new,  MOLECULE *mol_orig){  int i;  for (i = 0; i < 3; i++)    mol_new->transform.translate[i] += mol_orig->transform.translate[i];}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?