GLYLIB
0.3.0b
|
00001 /* 00002 * Functions for rotation about an axis 00003 * 00004 * author: Robert Davis 00005 * integrated with glylib by BLFoley 20110405 00006 */ 00007 00008 #include <mylib.h> 00009 #include <molecules.h> 00010 #include <geometries.h> 00011 00012 /** Create a rotation matrix for a rotation of theta degrees 00013 * about an axis through the given point in the given direction 00014 */ 00015 double * 00016 create_rotation_matrix(coord_3D point, vectormag_3D direction, double theta) 00017 { 00018 direction=normalize_vec(direction); 00019 if(direction.d==0){fprintf(stderr,"Attempting to rotate about a vector of zero length in create_rotation_matrix. Ignoring.\n");} 00020 double u = direction.i; 00021 double v = direction.j; 00022 double w = direction.k; 00023 00024 double a = point.i; 00025 double b = point.j; 00026 double c = point.k; 00027 00028 double *matrix = (double *)malloc(12 * sizeof(double)); 00029 double u2 = u*u; 00030 double v2 = v*v; 00031 double w2 = w*w; 00032 double cosT = cos(theta); 00033 double sinT = sin(theta); 00034 00035 matrix[3] = a*(v2 + w2) - u*(b*v + c*w) 00036 + (u*(b*v + c*w) - a*(v2 + w2))*cosT + (b*w - c*v)*sinT; 00037 00038 matrix[7] = b*(u2 + w2) - v*(a*u + c*w) 00039 + (v*(a*u + c*w) - b*(u2 + w2))*cosT + (c*u - a*w)*sinT; 00040 00041 matrix[11] = c*(u2 + v2) - w*(a*u + b*v) 00042 + (w*(a*u + b*v) - c*(u2 + v2))*cosT + (a*v - b*u)*sinT; 00043 00044 matrix[0] = (u2 + (v2 + w2) * cosT); 00045 matrix[1] = (u*v * (1 - cosT) - w*sinT); 00046 matrix[2] = (u*w * (1 - cosT) + v*sinT); 00047 00048 matrix[4] = (u*v * (1 - cosT) + w*sinT); 00049 matrix[5] = (v2 + (u2 + w2) * cosT); 00050 matrix[6] = (v*w * (1 - cosT) - u*sinT); 00051 00052 matrix[8] = (u*w * (1 - cosT) - v*sinT); 00053 matrix[9] = (v*w * (1 - cosT) + u*sinT); 00054 matrix[10] = (w2 + (u2 + v2) * cosT); 00055 00056 return matrix; 00057 } 00058 00059 void 00060 destroy_rotation_matrix(double *matrix) 00061 { 00062 free(matrix); 00063 } 00064 00065 void 00066 apply_rotation_matrix_to_coord_p(coord_3D *c, double *matrix) 00067 { 00068 coord_3D temp = *c; 00069 00070 c->i = matrix[0]*temp.i + matrix[1]*temp.j + matrix[2]*temp.k + matrix[3]; 00071 c->j = matrix[4]*temp.i + matrix[5]*temp.j + matrix[6]*temp.k + matrix[7]; 00072 c->k = matrix[8]*temp.i + matrix[9]*temp.j + matrix[10]*temp.k + matrix[11]; 00073 } 00074 00075 void 00076 rotate_coords_about_axis_dp_list(coord_3D **coords, int num_coords, coord_3D point, 00077 vectormag_3D direction, double theta) 00078 { 00079 int i; 00080 double *matrix; 00081 00082 matrix = create_rotation_matrix(point, direction, theta); 00083 for(i = 0; i < num_coords; i++) 00084 apply_rotation_matrix_to_coord_p(coords[i], matrix); 00085 00086 destroy_rotation_matrix(matrix); 00087 } 00088 00089 coord_3D 00090 get_cartesian_point_from_internal_coords(coord_3D a, coord_3D b, coord_3D c, 00091 double theta, double phi, double distance) 00092 { 00093 vectormag_3D lmn_x, lmn_y, lmn_z; 00094 double x_p, y_p, z_p; 00095 00096 vectormag_3D cb = get_vector_from_coords(c, b); 00097 vectormag_3D ba = get_vector_from_coords(b, a); 00098 00099 lmn_y = normalize_vec(get_crossprod(ba, cb)); 00100 lmn_z = normalize_vec(cb); 00101 lmn_x = get_crossprod(lmn_y, lmn_z); 00102 00103 x_p = distance * sin(theta) * cos(phi); 00104 y_p = distance * sin(theta) * sin(phi); 00105 z_p = distance * cos(theta); 00106 00107 return (coord_3D) {lmn_x.i*x_p + lmn_y.i*y_p + lmn_z.i*z_p + c.i, 00108 lmn_x.j*x_p + lmn_y.j*y_p + lmn_z.j*z_p + c.j, 00109 lmn_x.k*x_p + lmn_y.k*y_p + lmn_z.k*z_p + c.k}; 00110 } 00111