/* Copyright (C) 2001 Damir Zucic */

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

				omega_from_cacnca.c

Purpose:
	Calculate the dihedral angle omega, using CA and C atom from the
	previous residue and N and C atom from the current residue.  The
	peptide bond formed by the residues  I and  I + 1 is assigned to
	the residue I + 1 and not to the residue I.  The same applies to

Input:
	(1) Pointer to VectorS structure,  with CA atom coordinates from
	    the previous residue.
	(2) Pointer to VectorS structure,  with C  atom coordinates from
	    the previous residue.
	(3) Pointer to VectorS structure,  with N atom coordinates.
	(4) Pointer to VectorS structure,  with CA atom coordinates.
	(5) Pointer to ConfigS structure.

Output:
	Return value.

Return value:
	(1) Dihedral angle omega, on success.
	(2) BADDIHEDANGLE on failure.

========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"

/*======function prototypes:=================================================*/

void		VectorProduct_ (VectorS *, VectorS *, VectorS *);
double		ScalarProduct_ (VectorS *, VectorS *);
double		AbsoluteValue_ (VectorS *);

/*======calculate the omega angle:===========================================*/

double OmegaFromCACNCA_ (VectorS *prevCA_vectorSP, VectorS *prevC_vectorSP,
			 VectorS *N_vectorSP, VectorS *CA_vectorSP,
			 ConfigS *configSP)
{
VectorS		prevC_N_vectorS, prevC_prevCA_vectorS;
double		bond_length_squared;
VectorS		N_prevC_vectorS, N_CA_vectorS;
VectorS		u1S, u2S;
VectorS		v1S, v2S;
double		denom, ratio;
double		alpha, omega;

/* The first pair of auxiliary vectors: */
prevC_N_vectorS.x      = N_vectorSP->x      - prevC_vectorSP->x;
prevC_N_vectorS.y      = N_vectorSP->y      - prevC_vectorSP->y;
prevC_N_vectorS.z      = N_vectorSP->z      - prevC_vectorSP->z;
prevC_prevCA_vectorS.x = prevCA_vectorSP->x - prevC_vectorSP->x;
prevC_prevCA_vectorS.y = prevCA_vectorSP->y - prevC_vectorSP->y;
prevC_prevCA_vectorS.z = prevCA_vectorSP->z - prevC_vectorSP->z;

bond_length_squared = prevC_N_vectorS.x * prevC_N_vectorS.x +
		      prevC_N_vectorS.y * prevC_N_vectorS.y +
		      prevC_N_vectorS.z * prevC_N_vectorS.z;
if (bond_length_squared < configSP->C_N_min_squared) return BADDIHEDANGLE;
if (bond_length_squared > configSP->C_N_max_squared) return BADDIHEDANGLE;

/* The second pair of auxiliary vectors: */
N_prevC_vectorS.x = prevC_vectorSP->x - N_vectorSP->x;
N_prevC_vectorS.y = prevC_vectorSP->y - N_vectorSP->y;
N_prevC_vectorS.z = prevC_vectorSP->z - N_vectorSP->z;
N_CA_vectorS.x    = CA_vectorSP->x    - N_vectorSP->x;
N_CA_vectorS.y    = CA_vectorSP->y    - N_vectorSP->y;
N_CA_vectorS.z    = CA_vectorSP->z    - N_vectorSP->z;

/* Two vectors perpendicular to  prevC_N_vectorS,  mutually orthogonal, the */
/* second in the plane defined by prevC_N_vectorS and prevC_prevCA_vectorS: */
VectorProduct_ (&u1S, &prevC_N_vectorS, &prevC_prevCA_vectorS);
VectorProduct_ (&u2S, &u1S, &prevC_N_vectorS);

/* Two vectors perpendicular to  N_prevC_vectorS,  mutually orthogonal, */
/* the second in the plane defined by N_prevC_vectorS and N_CA_vectorS: */
VectorProduct_ (&v1S, &N_CA_vectorS, &N_prevC_vectorS);
VectorProduct_ (&v2S, &N_prevC_vectorS, &v1S);

/* Calculate the angle alpha, which will be used to calculate omega: */

/* Avoid division by zero: */
denom = AbsoluteValue_ (&u1S) * AbsoluteValue_ (&v1S);
if (denom == 0.0) return BADDIHEDANGLE;

/* Use the scalar product to calculate the cosine of the angle: */
ratio = ScalarProduct_ (&u1S, &v1S) / denom;

/* Arc cosine is very sensitive to floating point errors: */
if (ratio <= -1.0) alpha = 3.1415927;
else if (ratio >= 1.0) alpha = 0.0;
else alpha = acos (ratio);

/* There are two possible solutions; the right one is resolved here: */
if (ScalarProduct_ (&v2S, &u1S) >= 0) omega = alpha;
else omega = -alpha;

/* Return the angle (in radians): */
return omega;
}

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


