/* Copyright (C) 2000 Damir Zucic */

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

				calc_params.c

Purpose:
	Calculate some parameters, required  to speed up  projection of atom
	to the screen. These parameters depend on configuration, so they are
	stored to ConfigS structure.

Input:
	(1) Pointer to  ConfigS  structure,  where some data will be stored.
	(2) Pointer to GUIS structure,  with information  about screen size.

Output:
	(1) Some elements of ConfigS structure initialized.
	(2) Return value.

Return value:
	(1) Positive on success.
	(2) Negative 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		ErrorMessage_ (char *, char *, char *,
			       char *, char *, char *, char *);

/*======calculate auxiliary paramaters:======================================*/

int CalculateParameters_ (ConfigS *configSP, GUIS *guiSP)
{
double		sin_theta;

/* User-screen distance in atomic coordinates: */
if (configSP->screen_real_width == 0.0)
	{
	ErrorMessage_ ("garlic", "CalculateParameters_", "",
		"Screen real width not initialized!\n", "", "", "");
	return -1;
	}
configSP->user_screen_atomic_distance = configSP->user_screen_real_distance *
					configSP->screen_atomic_width /
					configSP->screen_real_width;

/* Screen height, in atomic coordinates: */
configSP->screen_atomic_height = configSP->screen_atomic_width *
				 configSP->screen_real_height /
				 configSP->screen_real_width;

/* Screen position in atomic coordinates, in absolute coordinate system: */
configSP->screen_atomic_z = configSP->user_atomic_position +
			    configSP->user_screen_atomic_distance;

/* Horizontal scale factor for conversion from atomic to screen units: */
if (configSP->screen_atomic_width == 0.0)
	{
	ErrorMessage_ ("garlic", "CalculateParameters_", "",
		"Screen atomic width not initialized!\n", "", "", "");
	return -2;
	}
configSP->atomic_to_screen_scale_x = (double) guiSP->screen_width /
				     configSP->screen_atomic_width;

/* Vertical scale factor for conversion from atomic to screen units: */
if (configSP->screen_atomic_height == 0.0)
	{
	ErrorMessage_ ("garlic", "CalculateParameters_", "",
		"Screen atomic height not initialized!\n", "", "", "");
	return -3;
	}
configSP->atomic_to_screen_scale_y = (double) guiSP->screen_height /
				     configSP->screen_atomic_height;

/* Horizontal scale factor for conversion from screen to atomic units: */
if (configSP->atomic_to_screen_scale_x != 0.0)
	{
	configSP->screen_to_atomic_scale_x = 1.0 /
				configSP->atomic_to_screen_scale_x;
	}
else configSP->screen_to_atomic_scale_x = 0.0;

/* Window free area width in atomic units: */
if (guiSP->screen_width == 0)
	{
	ErrorMessage_ ("garlic", "CalculateParameters_", "",
		"Screen width not initialized!\n", "", "", "");
	return -4;
	}
configSP->win_atomic_free_width = configSP->screen_atomic_width *
				  (double) guiSP->control_winS.x0 /
				  (double) guiSP->screen_width;

/* Window free area height in atomic units: */
if (guiSP->screen_height == 0)
	{
	ErrorMessage_ ("garlic", "CalculateParameters_", "",
		"Screen height not initialized!\n", "", "", "");
	return -5;
	}
configSP->win_atomic_free_height = configSP->screen_atomic_height *
				   (double) guiSP->input_winS.y0 /
				   (double) guiSP->screen_height;

/* Image extents, in screen units: */

/** Mono: **/
if (configSP->stereoF == 0)
	{
	configSP->image_screen_x0[0] = 0;
	configSP->image_screen_x1[0] = guiSP->control_winS.x0 - 1;
	}
/** Stereo: **/
else
	{
	configSP->image_screen_x0[0] = 0;
	configSP->image_screen_x1[0] = (guiSP->control_winS.x0 -
					configSP->stereo_screen_margin) / 2;
	configSP->image_screen_x0[1] = configSP->image_screen_x1[0] +
				       configSP->stereo_screen_margin;
	configSP->image_screen_x1[1] = guiSP->control_winS.x0 - 1;
	}
/** Both: **/
configSP->image_screen_y0 = 0;
configSP->image_screen_y1 = guiSP->input_winS.y0;

/* Positions of window edges, in atomic units: */

/** Mono: **/
if (configSP->stereoF == 0)
	{
	configSP->win_atomic_x1 =  configSP->win_atomic_free_width / 2.0;
	}
/** Stereo: **/
else
	{
	configSP->win_atomic_x1 =  configSP->win_atomic_free_width / 4.0;
	}
/** Both: **/
configSP->win_atomic_x0 = -configSP->win_atomic_x1;
configSP->win_atomic_y1 =  configSP->win_atomic_free_height / 2.0;
configSP->win_atomic_y0 = -configSP->win_atomic_y1;
configSP->win_atomic_z0 =  configSP->screen_atomic_z;

/* Data used to identify atoms  which are invisible and */
/* have invisible bonds (outside the window free area). */
/* Note that for mono image  the limits cover the whole */
/* window plus  one maximal bond  length on  each side! */
/* For stereo image horizontal limits cover half of the */
/* window  plus one  maximal bond  length on each side. */

/** Horizontal limits: **/
configSP->rationalized_x0 = (configSP->win_atomic_x0 -
			     configSP->max_bond_length) *
			     configSP->atomic_to_screen_scale_x;
configSP->rationalized_x1 = (configSP->win_atomic_x1 +
			     configSP->max_bond_length) *
			     configSP->atomic_to_screen_scale_x;
/** Vertical limits: **/
configSP->rationalized_y0 = (configSP->win_atomic_y0 -
			     configSP->max_bond_length) *
			     configSP->atomic_to_screen_scale_y;
configSP->rationalized_y1 = (configSP->win_atomic_y1 +
			     configSP->max_bond_length) *
			     configSP->atomic_to_screen_scale_y;

/* Image center, in screen units: */

/** Mono: **/
if (configSP->stereoF == 0)
	{
	configSP->center_screen_x[0] = guiSP->control_winS.x0 / 2;
	}
/** Stereo: **/
else
	{
	configSP->center_screen_x[0] = (guiSP->control_winS.x0 -
					configSP->stereo_screen_margin) / 4;
	configSP->center_screen_x[1] =  3 * configSP->center_screen_x[0] +
				        configSP->stereo_screen_margin;
	}
/** Both: **/
configSP->center_screen_y = guiSP->input_winS.y0 / 2;

/* The stereo internal margin, in atomic_units: */
if (configSP->atomic_to_screen_scale_x == 0)
	{
	ErrorMessage_ ("garlic", "CalculateParameters_", "",
		"Scale factor (atomic to screen units) not initialized!\n",
		"", "", "");
	return -6;
	}
configSP->stereo_atomic_margin = (double) configSP->stereo_screen_margin /
				 configSP->atomic_to_screen_scale_x;

/* Bond length parameters: */
configSP->C_C_min_squared = configSP->C_C_bond_length_min *
			    configSP->C_C_bond_length_min;
configSP->C_C_max_squared = configSP->C_C_bond_length_max *
			    configSP->C_C_bond_length_max;
configSP->C_N_min_squared = configSP->C_N_bond_length_min *
			    configSP->C_N_bond_length_min;
configSP->C_N_max_squared = configSP->C_N_bond_length_max *
			    configSP->C_N_bond_length_max;
configSP->C_O_min_squared = configSP->C_O_bond_length_min *
			    configSP->C_O_bond_length_min;
configSP->C_O_max_squared = configSP->C_O_bond_length_max *
			    configSP->C_O_bond_length_max;
configSP->C_S_min_squared = configSP->C_S_bond_length_min *
			    configSP->C_S_bond_length_min;
configSP->C_S_max_squared = configSP->C_S_bond_length_max *
			    configSP->C_S_bond_length_max;
configSP->C_H_min_squared = configSP->C_H_bond_length_min *
			    configSP->C_H_bond_length_min;
configSP->C_H_max_squared = configSP->C_H_bond_length_max *
			    configSP->C_H_bond_length_max;
configSP->N_O_min_squared = configSP->N_O_bond_length_min *
			    configSP->N_O_bond_length_min;
configSP->N_O_max_squared = configSP->N_O_bond_length_max *
			    configSP->N_O_bond_length_max;
configSP->N_H_min_squared = configSP->N_H_bond_length_min *
			    configSP->N_H_bond_length_min;
configSP->N_H_max_squared = configSP->N_H_bond_length_max *
			    configSP->N_H_bond_length_max;
configSP->O_H_min_squared = configSP->O_H_bond_length_min *
			    configSP->O_H_bond_length_min;
configSP->O_H_max_squared = configSP->O_H_bond_length_max *
			    configSP->O_H_bond_length_max;
configSP->S_H_min_squared = configSP->S_H_bond_length_min *
			    configSP->S_H_bond_length_min;
configSP->S_H_max_squared = configSP->S_H_bond_length_max *
			    configSP->S_H_bond_length_max;
configSP->O_P_min_squared = configSP->O_P_bond_length_min *
			    configSP->O_P_bond_length_min;
configSP->O_P_max_squared = configSP->O_P_bond_length_max *
			    configSP->O_P_bond_length_max;
configSP->S_S_min_squared = configSP->S_S_bond_length_min *
			    configSP->S_S_bond_length_min;
configSP->S_S_max_squared = configSP->S_S_bond_length_max *
			    configSP->S_S_bond_length_max;

configSP->generic_min_squared = configSP->generic_bond_length_min *
				configSP->generic_bond_length_min;
configSP->generic_max_squared = configSP->generic_bond_length_max *
				configSP->generic_bond_length_max;
configSP->hydro_min_squared = configSP->hydro_bond_length_min *
			      configSP->hydro_bond_length_min;
configSP->hydro_max_squared = configSP->hydro_bond_length_max *
                              configSP->hydro_bond_length_max;

/* The maximal CA-CA distance squared: */
configSP->CA_CA_dist_max_squared = configSP->CA_CA_dist_max *
				   configSP->CA_CA_dist_max;

/* The light source unit vector: */
sin_theta = sin (configSP->light_theta);
configSP->light_vectorS.x = sin_theta * cos (configSP->light_phi);
configSP->light_vectorS.y = sin_theta * sin (configSP->light_phi);
configSP->light_vectorS.z = cos (configSP->light_theta);

/* If this point is reached, everything worked fine: */
return 1;
}

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


