Beispiel #1
0
/* changing it so it rotates around the three principal axises - Adam Hogan */
void molecule_rotate_quaternion(molecule_t *molecule, double alpha, double beta, double gamma, int reverse_flag) {

	atom_t *atom_ptr;
	double com[3];
	int i, ii, n;
	double *new_coord_array;

	/* count the number of atoms in a molecule, and allocate new coords array */
	for(atom_ptr = molecule->atoms, n = 0; atom_ptr; atom_ptr = atom_ptr->next)
		++n;
	new_coord_array = calloc(n*3, sizeof(double));
	memnullcheck(new_coord_array,n*3*sizeof(double),__LINE__-1, __FILE__);

	/* save the com coordinate */
	com[0] = molecule->com[0];
	com[1] = molecule->com[1];
	com[2] = molecule->com[2];

	/* translate the molecule to the origin */
	for(atom_ptr = molecule->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
		atom_ptr->pos[0] -= com[0];
		atom_ptr->pos[1] -= com[1];
		atom_ptr->pos[2] -= com[2];
	}

	/* construct the rotation quaternions */
	struct quaternion first, second, third, total, total_conjugate, position, answer;
	//total = quaternion with no rotation
	quaternion_construct_xyzw(&total,0.,0.,0.,1.);
	//first = rotation around z axis
	quaternion_construct_axis_angle_degree(&first,0.,0.,1.,alpha);
	//second = rotation around y axis
	quaternion_construct_axis_angle_degree(&second,0.,1.,0.,beta);
	//third = rotation around z axis
	quaternion_construct_axis_angle_degree(&third,1.,0.,0.,gamma);
	//combine all rotations into total
	quaternion_multiplication(&first,&total,&total);
	quaternion_multiplication(&second,&total,&total);
	quaternion_multiplication(&third,&total,&total);
	//if we are undoing a rotation we need to conjugate total
	if (reverse_flag) quaternion_conjugate(&total,&total);
	quaternion_conjugate(&total,&total_conjugate);

	for(atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {

		ii = i*3;
		//position = position vector
		quaternion_construct_xyzw(&position,atom_ptr->pos[0],atom_ptr->pos[1],atom_ptr->pos[2],0.);

		//answer = total*(position*total_conjugate)
		quaternion_multiplication(&position,&total_conjugate,&answer);
		quaternion_multiplication(&total,&answer,&answer);

		//set the new coords
		new_coord_array[ii+0] = answer.x;
		new_coord_array[ii+1] = answer.y;
		new_coord_array[ii+2] = answer.z;

	}

	/* set the new coordinates and then translate back from the origin */
	for(atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {

		ii = i*3;
		atom_ptr->pos[0] = new_coord_array[ii+0];
		atom_ptr->pos[1] = new_coord_array[ii+1];
		atom_ptr->pos[2] = new_coord_array[ii+2];

		atom_ptr->pos[0] += com[0];
		atom_ptr->pos[1] += com[1];
		atom_ptr->pos[2] += com[2];

	}

	/* free our temporary array */
	free(new_coord_array);

}
Beispiel #2
0
/* now with quaternions AH */
void rotate(system_t *system, molecule_t *molecule, pbc_t *pbc, double scale) {
    atom_t *atom_ptr;
    double u1, u2, u3;
    double com[3];
    int i, ii, n;
    double *new_coord_array;

    struct quaternion position_vector, rnd_rotation, rnd_rotation_conjugate, answer;

    // create a random rotation
    // http://planning.cs.uiuc.edu/node198.html
    u1 = get_rand(system);
    u2 = get_rand(system);
    u3 = get_rand(system);

    // simple linear interpolation for adjusting the scale
    quaternion_construct_xyzw(&rnd_rotation, scale*sqrt(1-u1)*sin(2*M_PI*u2), scale*sqrt(1-u1)*cos(2*M_PI*u2), scale*sqrt(u1)*sin(2*M_PI*u3), 1-scale+scale*sqrt(u1)*cos(2*M_PI*u3)); /* make a random quaternion */
    quaternion_normalize(&rnd_rotation);
    quaternion_conjugate(&rnd_rotation, &rnd_rotation_conjugate);          /* needed to transform coordinates */

    /* count the number of atoms in a molecule, and allocate new coords array */
    for (atom_ptr = molecule->atoms, n = 0; atom_ptr; atom_ptr = atom_ptr->next)
        ++n;
    new_coord_array = calloc(n * 3, sizeof(double));
    memnullcheck(new_coord_array, n * 3 * sizeof(double), __LINE__ - 1, __FILE__);

    /* save the com coordinate */
    com[0] = molecule->com[0];
    com[1] = molecule->com[1];
    com[2] = molecule->com[2];

    /* translate the molecule to the origin */
    for (atom_ptr = molecule->atoms; atom_ptr; atom_ptr = atom_ptr->next) {
        atom_ptr->pos[0] -= com[0];
        atom_ptr->pos[1] -= com[1];
        atom_ptr->pos[2] -= com[2];
    }

    /* quaternion multiply */
    for (atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {
        ii = i * 3;

        //position_vector = position
        quaternion_construct_xyzw(&position_vector, atom_ptr->pos[0], atom_ptr->pos[1], atom_ptr->pos[2], 0.);

        //answer = rnd_rotation*(position*rnd_rotation_conjugate)
        quaternion_multiplication(&position_vector, &rnd_rotation_conjugate, &answer);
        quaternion_multiplication(&rnd_rotation, &answer, &answer);

        //set the new coords
        new_coord_array[ii + 0] = answer.x;
        new_coord_array[ii + 1] = answer.y;
        new_coord_array[ii + 2] = answer.z;
    }

    /* set the new coordinates and then translate back from the origin */
    for (atom_ptr = molecule->atoms, i = 0; atom_ptr; atom_ptr = atom_ptr->next, i++) {
        ii = i * 3;
        atom_ptr->pos[0] = new_coord_array[ii + 0];
        atom_ptr->pos[1] = new_coord_array[ii + 1];
        atom_ptr->pos[2] = new_coord_array[ii + 2];

        atom_ptr->pos[0] += com[0];
        atom_ptr->pos[1] += com[1];
        atom_ptr->pos[2] += com[2];
    }

    /* free our temporary array */
    free(new_coord_array);
}