/* Copyright (C) 2000 Damir Zucic */

/*=============================================================================

				rotate_plane.c

Purpose:
	Rotate the plane associated with the given macromolecular complex.

Input:
	(1) Pointer to MolComplexS structure.
	(2) Pointer to ConfigS structure.
	(3) Rotation angle.
	(4) Rotation axis identifier (1 = x, 2 = y, 3 = z).

Output:
	(1) Plane rotated, stereo data updated.

Return value:
	No return value.

========includes:============================================================*/

#include <stdio.h>

#include <math.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "typedefs.h"

/*======rotate plane:========================================================*/

void RotatePlane_ (MolComplexS *curr_mol_complexSP, ConfigS *configSP,
		   double rotation_angle, int axisID)
{
double		cos_angle, sin_angle;
double		cos_stereo_angle, sin_stereo_angle;
PlaneS		*curr_planeSP;
double		x0, y0, z0;
double		x, y, z;
static double	x_new, y_new, z_new;

/* Calculate cosine and sine of the rotation angle: */
cos_angle = cos (rotation_angle);
sin_angle = sin (rotation_angle);

/* Calculate cosine and sine of the stereo angle: */
cos_stereo_angle = cos (configSP->stereo_angle);
sin_stereo_angle = sin (configSP->stereo_angle);

/* Pointer to the current plane: */
curr_planeSP = &curr_mol_complexSP->planeS;

/* If plane is moved together with the structure, rotate the plane center: */
if (curr_mol_complexSP->move_bits & STRUCTURE_MASK)
	{
	/* Copy the rotation center coordinates: */
	x0 = curr_mol_complexSP->rotation_center_vectorS.x;
	y0 = curr_mol_complexSP->rotation_center_vectorS.y;
	z0 = curr_mol_complexSP->rotation_center_vectorS.z;

	/* Position of the plane center relative to the rotation center: */
	x = curr_planeSP->center_x[0] - x0;
	y = curr_planeSP->center_y    - y0;
	z = curr_planeSP->center_z[0] - z0;

	/* Rotate these coordinates: */
	switch (axisID)
		{
		/* Rotate around x: */
		case 1:
			x_new =  x;
			y_new =  y * cos_angle - z * sin_angle;
			z_new =  y * sin_angle + z * cos_angle;
			break;

		/* Rotate around y: */
		case 2:
			x_new =  x * cos_angle + z * sin_angle;
			y_new =  y;
			z_new = -x * sin_angle + z * cos_angle;
			break;

		/* Rotate around z: */
		case 3:
			x_new =  x * cos_angle - y * sin_angle;
			y_new =  x * sin_angle + y * cos_angle;
			z_new =  z;
			break;

		/* The impossible case: */
		default:
			;
			break;
		}
	/* Translate and store new coordinates: */
	curr_planeSP->center_x[0] = x_new + x0;
	curr_planeSP->center_y    = y_new + y0;
	curr_planeSP->center_z[0] = z_new + z0;

	/* Prepare stereo data: */
	x0 = curr_mol_complexSP->geometric_center_vectorS.x;
	z0 = curr_mol_complexSP->geometric_center_vectorS.z;
	x = curr_planeSP->center_x[0] - x0;
	z = curr_planeSP->center_z[0] - z0;
	x_new =  x * cos_stereo_angle + z * sin_stereo_angle;
	z_new = -x * sin_stereo_angle + z * cos_stereo_angle;

	curr_planeSP->center_x[1] = x_new + x0;
	curr_planeSP->center_z[1] = z_new + z0;
	}

/* Copy the normal vector components: */
x = curr_planeSP->normal_x[0];
y = curr_planeSP->normal_y;
z = curr_planeSP->normal_z[0];

/* Rotate the normal vector: */
switch (axisID)
	{
	/* Rotate around x: */
	case 1:
		x_new =  x;
		y_new =  y * cos_angle - z * sin_angle;
		z_new =  y * sin_angle + z * cos_angle;
		break;

	/* Rotate around y: */
	case 2:
		x_new =  x * cos_angle + z * sin_angle;
		y_new =  y;
		z_new = -x * sin_angle + z * cos_angle;
		break;

	/* Rotate around z: */
	case 3:
		x_new =  x * cos_angle - y * sin_angle;
		y_new =  x * sin_angle + y * cos_angle;
		z_new =  z;
		break;

	/* The impossible case: */
	default:
		;
		break;
	}

/* Store the rotated vector: */
curr_planeSP->normal_x[0] = x_new;
curr_planeSP->normal_y    = y_new;
curr_planeSP->normal_z[0] = z_new;

/* Prepare stereo data for normal vector: */
curr_planeSP->normal_x[1] =  curr_planeSP->normal_x[0] * cos_stereo_angle +
			     curr_planeSP->normal_z[0] * sin_stereo_angle;
curr_planeSP->normal_z[1] = -curr_planeSP->normal_x[0] * sin_stereo_angle +
			     curr_planeSP->normal_z[0] * cos_stereo_angle;

/* Set the position_changedF: */
curr_mol_complexSP->position_changedF = 1;
}

/*===========================================================================*/


