/* Copyright (C) 2003 Damir Zucic */

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

				select_tm.c

Purpose:
	Select transmembrane part of the macromolecular complex. 

Input:
	(1) Pointer to MolComplexS structure, with macromol. complexes.
	(2) Number of macromolecular complexes.
	(3) Selection mode index  (0 = overwrite, 1 = restrict, 2 = expand
	    previous selection).

Output:
	(1) The  flag  selectedF  set to one  for selected atoms  in every
	    caught macromolecular complex.
	(2) Return value.

Return value:
	(1) The number of selected atoms (zero or positive value).

Notes:
	(1) Half of the membrane thickness is expanded by two angstroms to
	    include atoms which are outside, but close to the membrane.

========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:=================================================*/

double		ScalarProduct_ (VectorS *, VectorS *);

/*======select transmembrane part:===========================================*/

long SelectTM_ (MolComplexS *mol_complexSP, int mol_complexesN,
		int selection_modeI)
{
long		selected_atomsN = 0;
int		mol_complexI;
MolComplexS	*curr_mol_complexSP;
size_t		atomsN, atomI;
VectorS		normal_vectorS;
double		membrane_center_x, membrane_center_y, membrane_center_z;
double		half_thickness;
AtomS		*curr_atomSP;
double		x, y, z;
VectorS		curr_vectorS;
int		transmembraneF;
double		projection;
double		absolute_value;

/* Select all atoms above the plane: */
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
	{
	/* Pointer to the current macromolecular complex: */
	curr_mol_complexSP = mol_complexSP + mol_complexI;

	/* Check is the current macromolecular complex caught: */
	if (curr_mol_complexSP->catchF == 0) continue;

	/* Number of atoms in a macromolecular complex: */
	atomsN = curr_mol_complexSP->atomsN;
	if (atomsN == 0) continue;

	/* Check is membrane defined at all: */
	if (curr_mol_complexSP->membraneS.definedF == 0) continue;

	/* The normal vector: */ 
	normal_vectorS.x = curr_mol_complexSP->membraneS.plane1S.normal_x[0];
	normal_vectorS.y = curr_mol_complexSP->membraneS.plane1S.normal_y;
	normal_vectorS.z = curr_mol_complexSP->membraneS.plane1S.normal_z[0];

	/* Position of the plane center: */
	membrane_center_x = curr_mol_complexSP->membraneS.center_x;
	membrane_center_y = curr_mol_complexSP->membraneS.center_y;
	membrane_center_z = curr_mol_complexSP->membraneS.center_z;

	/* Half of the membrane thickness enlarged by a margin of */
	/* two angstroms.  This margin  allows inclusion  of some */
	/* atoms which are outside the TM area,  but not too far. */
	half_thickness = 0.5 * curr_mol_complexSP->membraneS.thickness + 2.0;

	/* Scan all atoms in the current complex: */
	for (atomI = 0; atomI < atomsN; atomI++)
		{
		/* Pointer to the current atom: */
		curr_atomSP = curr_mol_complexSP->atomSP + atomI;

		/* Copy the coordinates: */
		x = curr_atomSP->raw_atomS.x[0];
		y = curr_atomSP->raw_atomS.y;
		z = curr_atomSP->raw_atomS.z[0];

		/* Position of the atom relative to the membrane center: */
		curr_vectorS.x = x - membrane_center_x;
		curr_vectorS.y = y - membrane_center_y;
		curr_vectorS.z = z - membrane_center_z;

		/* Reset the flag: */
		transmembraneF = 0;

		/* Check the scalar product with the unit direction vector: */
		projection = ScalarProduct_ (&curr_vectorS, &normal_vectorS);

		/* Take the absolute value: */
		absolute_value = fabs (projection);

		/* Compare this value with half of the membrane thickness: */
		if (absolute_value <= half_thickness) transmembraneF = 1;

		/* Set the selection flag for the current atom: */
		switch (selection_modeI)
			{
			/* Overwrite the previous selection: */
			case 0:
				curr_atomSP->selectedF = transmembraneF;
				break;

			/* Restrict the previous selection: */
			case 1:
				curr_atomSP->selectedF &= transmembraneF;
				break;

			/* Expand the previous selection: */
			case 2:
				curr_atomSP->selectedF |= transmembraneF;
				break;

			default:
				;
			}

		/* Check the selection flag; increase */
		/* the count if flag is equal to one: */
		if (curr_atomSP->selectedF) selected_atomsN++;
		}
	}

/* Return the number of selected atoms: */
return selected_atomsN;
}

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


