/* Copyright (C) 2001-2002 Damir Zucic */

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

				small_omega.c

Purpose:
	Draw small plot showing  the current omega angle with statistical
	distribution of omega values. This plot is used while editing the
	omega angle.  The distribution was derived  using a collection of
	high resolution X-ray structures (1.00 angstroms or better).  The
	plot is placed to the bottom right corner.
	
Input:
	(1) Pointer to MolComplexS structure.
	(2) Pointer to RuntimeS structure.
	(3) Pointer to GUIS structure.

Output:
	(1) Small omega plot drawn to the hidden pixmap.
	(2) Return value.

Return value:
	(1) Positive on success.
	(2) Negative on failure.

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

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

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

int		ParseColor_ (RGBS *, unsigned long *, GUIS *, char *, char *);

/*======draw small omega plot:===============================================*/

int SmallOmega_ (MolComplexS *mol_complexSP, RuntimeS *runtimeSP, GUIS *guiSP)
{
int			residuesN, residueI;
int			chosen_residue_foundF;
static ResidueS		*residueSP;
size_t			atom_startI, atom_endI;
static AtomS		*first_atomSP;
int			inner_width, inner_height, outer_width, outer_height;
int			screen_x0, screen_y0, screen_x1, screen_y1;
RGBS			rgbS;
unsigned long		colorID;
static double		peak1_xA[19] = {0.000, 0.054, 0.045, 0.040, 0.036,
					0.030, 0.026, 0.020, 0.017, 0.015,
					0.014, 0.011, 0.010, 0.007, 0.006,
					0.004, 0.002, 0.001, 0.001};
static double		peak1_yA[19] = {1.000, 1.000, 0.920, 0.850, 0.810,
					0.770, 0.700, 0.670, 0.613, 0.558,
					0.482, 0.392, 0.302, 0.251, 0.231,
					0.206, 0.186, 0.161, 1.000};
static int		peak1_pointsN = 19;

static double		peak2_xA[6]  = {0.521, 0.497, 0.474, 0.456, 0.432,
					0.425};
static double		peak2_yA[6]  = {1.000, 0.980, 0.982, 0.982, 0.980,
					1.000};
static int		peak2_pointsN = 6;

static double		peak3_xA[20] = {1.000, 0.999, 0.996, 0.994, 0.991,
					0.990, 0.989, 0.987, 0.987, 0.983,
					0.980, 0.977, 0.973, 0.971, 0.965,
					0.962, 0.958, 0.951, 0.945, 0.938};
static double		peak3_yA[20] = {1.000, 0.106, 0.025, 0.015, 0.050,
					0.080, 0.126, 0.251, 0.362, 0.467,
					0.603, 0.729, 0.814, 0.859, 0.905,
					0.935, 0.960, 0.975, 0.985, 1.000};
static int		peak3_pointsN = 20;

int			pointI;
XPoint			pointSA[30];
double			d;
int			omegaI;

/* Prepare and check the number of residues: */
residuesN = mol_complexSP->residuesN;
if (residuesN <= 0) return -1;

/* Find the residue to which the omega plot will be assigned: */
chosen_residue_foundF = 0;
for (residueI = 0; residueI < residuesN; residueI++)
	{
	/* Pointer to the current residue: */
	residueSP = mol_complexSP->residueSP + residueI;

	/* Prepare the atomic index range: */
	atom_startI = residueSP->residue_startI;
	atom_endI   = residueSP->residue_endI;

	/* Pointer to the first atom of the current residue: */
	first_atomSP = mol_complexSP->atomSP + atom_startI;

	/* Editing of a single omega angle requested: */
	if (runtimeSP->edit_single_bondF)
		{
		/* Check the array index of N atom, it is assumed that */
		/* it was stored as  the second array index somewhere: */
		if ((runtimeSP->atom2_arrayI >= atom_startI) &&
		    (runtimeSP->atom2_arrayI <= atom_endI))
			{
			chosen_residue_foundF = 1;
			break;
			}
		}

	/* Editing of omega for all selected residues requested: */
	else
		{
		/* If the first atom of the current residue is */
		/* selected,  treat this residue  as selected: */
		if (first_atomSP->selectedF)
			{
			chosen_residue_foundF = 1;
			break;
			}
		}
	}

/* Check was residue found at all: */
if (!chosen_residue_foundF) return -2;

/* The width and height of the omega plot: */
inner_width  = (int) guiSP->main_win_free_area_width - 11;
if (inner_width < 10) inner_width = 10;
inner_height = (int) guiSP->main_win_free_area_height / 8;
if (inner_height < 10) inner_height = 10;
outer_width  = inner_width  + 8;
outer_height = inner_height + 8;

/* The top left corner of the background square: */
screen_x0 = 1;
screen_y0 = guiSP->main_win_free_area_height - outer_height - 2;

/* Draw the filled square. Use a shade of orange color: */
ParseColor_ (&rgbS, &colorID, guiSP, "RGB:D8D8/B7B7/9999", "white");
XSetForeground (guiSP->displaySP, guiSP->theGCA[0], colorID);
XFillRectangle (guiSP->displaySP,
		guiSP->main_hidden_pixmapID,
		guiSP->theGCA[0],
		screen_x0, screen_y0,
		outer_width, outer_height);

/* Draw the border, using the main window foreground color: */
XSetForeground (guiSP->displaySP, guiSP->theGCA[0],
		guiSP->main_winS.fg_colorID);
XDrawRectangle (guiSP->displaySP,
		guiSP->main_hidden_pixmapID,
		guiSP->theGCA[0],
		screen_x0, screen_y0,
		outer_width, outer_height);

/* Draw peaks. */

/* Prepare a shade of blue: */
ParseColor_ (&rgbS, &colorID, guiSP, "RGB:2222/5555/DDDD", "white");
XSetForeground (guiSP->displaySP, guiSP->theGCA[0], colorID);

/* The XPoint structures for the first filled polygon: */
for (pointI = 0; pointI < peak1_pointsN; pointI++)
	{
	d = guiSP->main_win_free_area_width  - outer_width  + 2 +
	    inner_width  * peak1_xA[pointI];
	pointSA[pointI].x = (short) d;
	d = guiSP->main_win_free_area_height - outer_height + 2 +
	    inner_height * peak1_yA[pointI];
	pointSA[pointI].y = (short) d;
	}

/* Draw the first filled polygon: */
XFillPolygon (guiSP->displaySP, guiSP->main_hidden_pixmapID, guiSP->theGCA[0],
	      pointSA, peak1_pointsN, Nonconvex, CoordModeOrigin);

/* The XPoint structures for the second filled polygon: */
for (pointI = 0; pointI < peak2_pointsN; pointI++)
	{
	d = guiSP->main_win_free_area_width  - outer_width  + 2 +
	    inner_width  * peak2_xA[pointI];
	pointSA[pointI].x = (short) d;
	d = guiSP->main_win_free_area_height - outer_height + 2 +
	    inner_height * peak2_yA[pointI];
	pointSA[pointI].y = (short) d;
	}

/* Draw the second filled polygon: */
XFillPolygon (guiSP->displaySP, guiSP->main_hidden_pixmapID, guiSP->theGCA[0],
	      pointSA, peak2_pointsN, Nonconvex, CoordModeOrigin);

/* The XPoint structures for the third filled polygon: */
for (pointI = 0; pointI < peak3_pointsN; pointI++)
	{
	d = guiSP->main_win_free_area_width  - outer_width  + 2 +
	    inner_width  * peak3_xA[pointI];
	pointSA[pointI].x = (short) d;
	d = guiSP->main_win_free_area_height - outer_height + 2 +
	    inner_height * peak3_yA[pointI];
	pointSA[pointI].y = (short) d;
	}

/* Draw the third filled polygon: */
XFillPolygon (guiSP->displaySP, guiSP->main_hidden_pixmapID, guiSP->theGCA[0],
	      pointSA, peak3_pointsN, Nonconvex, CoordModeOrigin);

/* Prepare black color: */
XSetForeground (guiSP->displaySP, guiSP->theGCA[0], guiSP->black_colorID);

/* Draw bounding rectangle: */
screen_x0 = guiSP->main_win_free_area_width  - outer_width  + 2;
screen_y0 = guiSP->main_win_free_area_height - outer_height + 2;
XDrawRectangle (guiSP->displaySP,
		guiSP->main_hidden_pixmapID,
		guiSP->theGCA[0],
		screen_x0, screen_y0,
		inner_width, inner_height);

/* Draw vertical grid using the spacing of 90 degrees: */
screen_x0 = guiSP->main_win_free_area_width  - outer_width  + 2;
screen_y0 = guiSP->main_win_free_area_height - outer_height + 2;
screen_y1 = screen_y0 + inner_height;
for (omegaI = 0; omegaI <= 5; omegaI++)
	{
	d = (double) inner_width * ((double) omegaI * 0.25) + 0.5;
	screen_x1 = screen_x0 + (int) d;
	XDrawLine (guiSP->displaySP,
		   guiSP->main_hidden_pixmapID,
		   guiSP->theGCA[0],
		   screen_x1, screen_y0,
		   screen_x1, screen_y1);
	}

/* Draw the symbol at the position defined by the omega value. */

/* Prepare the symbol position: */
d = (double) inner_width  * (residueSP->omega + 3.1415927) * 0.15915494;
screen_x0 = guiSP->main_win_free_area_width  - outer_width  + 2 + (int) d;
screen_y0 = guiSP->main_win_free_area_height - outer_height + 2;

/* Draw the inner part of the symbol (yellow): */
XSetForeground (guiSP->displaySP, guiSP->theGCA[0], guiSP->yellow_colorID);
XFillRectangle (guiSP->displaySP,
		guiSP->main_hidden_pixmapID,
		guiSP->theGCA[0],
		screen_x0 - 1, screen_y0, 1, inner_height);

/* Draw the outer part of the symbol (red): */
XSetForeground (guiSP->displaySP, guiSP->theGCA[0], guiSP->red_colorID);
XDrawRectangle (guiSP->displaySP,
		guiSP->main_hidden_pixmapID,
		guiSP->theGCA[0],
		screen_x0 - 2, screen_y0, 2, inner_height);

/* Return positive value on success: */
return 1;
}

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


