/* Copyright (C) 2000 Damir Zucic */

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

				half_sphere_slab.c

Purpose:
	Check which atoms are inside the semi-spherical slab.  Semi-spher.
	slab is	 defined by  two concentric  spheres and  a single  plane,
	passing through  the slab center.  A given atom is inside the slab
	if it is outside the inner sphere,  inside the outer sphere and in
	front of  the plane.  Use this slab type  to hide  the entire rear
	half as well as the inner part of a globular protein. The position
	of the  plane  is  fixed,  while  the position  of both  spherical
	surfaces may be adjusted.

Input:
	(1) Pointer to MolComplexS structure.

Output:
	(1) Slab flag  set for  each atom.  The value  one  is assigned to
	    atoms inside the slab, zero to the rest.
	(2) Return value.

Return value:
	The number of atoms inside the slab.

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

#include <stdio.h>

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

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

/*======semi-spherical slab:=================================================*/

size_t HalfSphereSlab_ (MolComplexS *curr_mol_complexSP)
{
size_t		atoms_inside_slabN = 0;
size_t		atomsN, atomI;
AtomS		*curr_atomSP;
double		x0, y0, z0, r0_squared, r1_squared;
double		x, y, z, rho_squared, r_squared;

/* The number of atoms in a complex: */
atomsN = curr_mol_complexSP->atomsN;

/* Copy the slab center coordinates: */
x0 = curr_mol_complexSP->slab_center_vectorS.x;
y0 = curr_mol_complexSP->slab_center_vectorS.y;
z0 = curr_mol_complexSP->slab_center_vectorS.z;
r0_squared = curr_mol_complexSP->slab_back_relative_position;
r0_squared *= r0_squared;
r1_squared = curr_mol_complexSP->slab_front_relative_position;
r1_squared *= r1_squared;

/* Set the slab flag for each atom: */
for (atomI = 0; atomI < atomsN; atomI++)
	{
	/** Pointer to the current atom: **/
	curr_atomSP = curr_mol_complexSP->atomSP + atomI;

	/** Set the initial values of slab flags to one; this **/
	/** will be changed later for atoms outside the slab: **/
	curr_atomSP->inside_slabF = 1;
	curr_atomSP->inside_projected_slabF = 1;

	/** Distance between the current atom and the cylinder axis: **/
	x = curr_atomSP->raw_atomS.x[0] - x0;
	z = curr_atomSP->raw_atomS.z[0] - z0;
	rho_squared = x * x + z * z;

	/** Distance between the current atom and the slab center: **/
	y = curr_atomSP->raw_atomS.y - y0;
	r_squared = rho_squared + y * y;

	/** First prepare the inside_projected_slabF: */
	if (rho_squared < r0_squared) curr_atomSP->inside_projected_slabF = 0;
	if (rho_squared > r1_squared) curr_atomSP->inside_projected_slabF = 0;

	/** If atom is behind  the back plane,  set slab **/
	/** flags to zero and go to check the next atom: **/
	if (z > 0.0)
		{
		curr_atomSP->inside_slabF = 0;
		curr_atomSP->inside_projected_slabF = 0;
		continue;
		}

	/** If atom is inside  the inner slab sphere: **/
	if (r_squared < r0_squared)
		{
		curr_atomSP->inside_slabF = 0;
		continue;
		}

	/** If atom is outside the outer slab sphere: **/
	if (r_squared > r1_squared)
		{
		curr_atomSP->inside_slabF = 0;
		continue;
		}

	/** If this points is reached, current atom is inside the slab: **/
	atoms_inside_slabN++;
	}

/* Return the number of atoms inside the slab: */
return atoms_inside_slabN;
}

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

