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

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

				bond_style3_quad3.c

Purpose:
	Draw bond which fits into quadrant 3 using style 3. See the file
	file bonds_style3.c for description of quadrants.

Input:
	(1) Pointer to Aux1S structure, which contains required data.
	(2) Bond index.

Output:
	(1) A single bond drawn.
	(2) Return value.

Return value:
	(1) One if at least one pixel is drawn.
	(2) Zero otherwise.

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

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

/*======draw bond in quadrant 3 using style 3:===============================*/

int BondStyle3Quadrant3_ (Aux1S *aux1SP, int bondI)
{
long			pixels_drawnN = 0;
double			recip_denom, x_to_y_scale, x_to_z_scale;
int			screen_x, screen_x1, delta_x, screen_y, line_screen_y;
double			d, atomic_z;
int			lineI;
size_t			pixelI;
NearestAtomS		*curr_pixelSP;

/* Scale factor required to calculate screen_y from screen_x: */
if (aux1SP->screen_delta_x != 0)
	recip_denom = 1.0 / (double) aux1SP->screen_delta_x;
else recip_denom = 0.0;
x_to_y_scale = (double) aux1SP->screen_delta_y * recip_denom;

/* Scale factor required to calculate z (in atomic units) from screen_x: */
x_to_z_scale = aux1SP->atomic_delta_z * recip_denom;

/* Horizontal scan, from right to left: */
screen_x1 = (aux1SP->screen_x0 + aux1SP->screen_x1) / 2;
for (screen_x = aux1SP->screen_x0; screen_x >= screen_x1; screen_x--)
	{
	/* Check is this pixel inside the area reserved for the */
	/* current image (there are two images in stereo mode): */
	if (screen_x < aux1SP->configSP->image_screen_x0[aux1SP->imageI])
		{
		continue;
		}
	if (screen_x > aux1SP->configSP->image_screen_x1[aux1SP->imageI])
		{
		continue;
		}

	/* Relative position: */
	delta_x = screen_x - aux1SP->screen_x0;

	/* Find the corresponding screen_y: */
	d = (double) aux1SP->screen_y0 + x_to_y_scale * (double) delta_x;
	screen_y = (int) (d + 0.5);

	/* z value (in atomic units): */
	atomic_z = aux1SP->atomic_z0 + x_to_z_scale * (double) delta_x;

	/* Loop which draws five lines (vertical scan): */
	for (lineI = 0; lineI <= 4; lineI++)
		{
		/* Pixel position: */
		line_screen_y = screen_y +lineI - 2;

		/* Check is this pixel inside the area reserved for the */
		/* current image (there are two images in stereo mode): */
		if (line_screen_y < aux1SP->configSP->image_screen_y0)
			{
			continue;
			}
		if (line_screen_y > aux1SP->configSP->image_screen_y1)
			{
			continue;
			}

		/* Current pixel index: */
		pixelI = aux1SP->guiSP->main_win_free_area_width *
			 line_screen_y + screen_x;

		/* Check pixel index: */
		if (pixelI >= aux1SP->pixelsN) break;

		/* Pointer to  NearestAtomS struct. */
		/* assigned to current coordinates: */
		curr_pixelSP = aux1SP->nearest_atomSP + pixelI;

		/* Check was  this pixel used  already in */
		/* this drawing step;  if it was, compare */
		/* the z value of the current atom with z */
		/* value previously stored to this pixel: */
		if (aux1SP->refreshI == curr_pixelSP->last_refreshI)
			{
			if (atomic_z >= curr_pixelSP->z) continue;
			}

		/* If this point is reached draw pixel: */
	        XDrawPoint (aux1SP->guiSP->displaySP,
			    aux1SP->guiSP->main_hidden_pixmapID,
			    aux1SP->guiSP->theGCA[lineI],
			    screen_x, line_screen_y);

		/* Refresh the content of NearestAtomS */
		/* array  associated  with this pixel: */
		curr_pixelSP->styleI = 3;
		curr_pixelSP->last_refreshI = aux1SP->refreshI;
		curr_pixelSP->mol_complexI = aux1SP->mol_complexI;
		curr_pixelSP->atomI = aux1SP->atomI;
		curr_pixelSP->bondI = bondI;
		curr_pixelSP->z = atomic_z;
		curr_pixelSP->colorID = aux1SP->colorIDA[lineI];

		/* Update the number of pixels drawn: */
		pixels_drawnN++;
		}
	}

/* Rounding the right end: */
do
	{
	/* The x coordinate: */
	screen_x = aux1SP->screen_x0 + 1;

	/* Check: */
	if (screen_x < aux1SP->configSP->image_screen_x0[aux1SP->imageI]) break;
	if (screen_x > aux1SP->configSP->image_screen_x1[aux1SP->imageI]) break;

	/* z value (in atomic units): */
	atomic_z = aux1SP->atomic_z0;

	/* The y coordinate of central pixel: */
	screen_y = aux1SP->screen_y0;

	/* Scan three lines: */
	for (lineI = 0; lineI <= 2; lineI++)
		{
		/* Pixel position: */
		line_screen_y = screen_y +lineI - 1;

		/* Check: */
		if (line_screen_y < aux1SP->configSP->image_screen_y0) continue;
		if (line_screen_y > aux1SP->configSP->image_screen_y1) continue;

		/* Current pixel index: */
		pixelI = aux1SP->guiSP->main_win_free_area_width *
			 line_screen_y + screen_x;

		/* Check pixel index: */
		if (pixelI >= aux1SP->pixelsN) break;

		/* Pointer to  NearestAtomS struct. */
		/* assigned to current coordinates: */
		curr_pixelSP = aux1SP->nearest_atomSP + pixelI;

		/* Check was this pixel used already in this drawing step : */
		if (aux1SP->refreshI == curr_pixelSP->last_refreshI)
			{
			if (atomic_z >= curr_pixelSP->z) continue;
			}

		/* If this point is reached draw one pixel: */
		XDrawPoint (aux1SP->guiSP->displaySP,
			    aux1SP->guiSP->main_hidden_pixmapID,
			    aux1SP->guiSP->theGCA[lineI + 1],
			    screen_x, line_screen_y);

		/* Refresh the content of NearestAtomS */
		/* array  associated  with this pixel: */
		curr_pixelSP->styleI = 3;
		curr_pixelSP->last_refreshI = aux1SP->refreshI;
		curr_pixelSP->mol_complexI = aux1SP->mol_complexI;
		curr_pixelSP->atomI = aux1SP->atomI;
		curr_pixelSP->bondI = bondI;
		curr_pixelSP->z = atomic_z;
		curr_pixelSP->colorID = aux1SP->colorIDA[lineI + 1];

		/* Update the number of pixels drawn: */
		pixels_drawnN++;
		}

	/* End of single pass loop: */
	} while (0);

/* Rounding the left end: */
do
	{
	/* The x coordinate: */
	screen_x = screen_x1 - 1;

	/* Check: */
	if (screen_x < aux1SP->configSP->image_screen_x0[aux1SP->imageI]) break;
	if (screen_x > aux1SP->configSP->image_screen_x1[aux1SP->imageI]) break;

	/* Relative position: */
	delta_x = screen_x1 - aux1SP->screen_x0;

	/* z value (in atomic units): */
	atomic_z = aux1SP->atomic_z0 + x_to_z_scale * (double) delta_x;

	/* The y coordinate of central pixel: */
	d = (double) aux1SP->screen_y0 + x_to_y_scale * (double) delta_x;
	screen_y = (int) (d + 0.5);

	/* Scan three lines: */
	for (lineI = 0; lineI <= 2; lineI++)
		{
		/* Pixel position: */
		line_screen_y = screen_y +lineI - 1;

		/* Check: */
		if (line_screen_y < aux1SP->configSP->image_screen_y0) continue;
		if (line_screen_y > aux1SP->configSP->image_screen_y1) continue;

		/* Current pixel index: */
		pixelI = aux1SP->guiSP->main_win_free_area_width *
			 line_screen_y + screen_x;

		/* Check pixel index: */
		if (pixelI >= aux1SP->pixelsN) break;

		/* Pointer to  NearestAtomS struct. */
		/* assigned to current coordinates: */
		curr_pixelSP = aux1SP->nearest_atomSP + pixelI;

		/* Check was this pixel used already in this drawing step : */
		if (aux1SP->refreshI == curr_pixelSP->last_refreshI)
			{
			if (atomic_z >= curr_pixelSP->z) continue;
			}

		/* If this point is reached draw one pixel: */
		XDrawPoint (aux1SP->guiSP->displaySP,
			    aux1SP->guiSP->main_hidden_pixmapID,
			    aux1SP->guiSP->theGCA[lineI + 1],
			    screen_x, line_screen_y);

		/* Refresh the content of NearestAtomS */
		/* array  associated  with this pixel: */
		curr_pixelSP->styleI = 3;
		curr_pixelSP->last_refreshI = aux1SP->refreshI;
		curr_pixelSP->mol_complexI = aux1SP->mol_complexI;
		curr_pixelSP->atomI = aux1SP->atomI;
		curr_pixelSP->bondI = bondI;
		curr_pixelSP->z = atomic_z;
		curr_pixelSP->colorID = aux1SP->colorIDA[lineI + 1];

		/* Update the number of pixels drawn: */
		pixels_drawnN++;
		}

	/* End of single pass loop: */
	} while (0);

/* Check is at least one pixel drawn: */
if (pixels_drawnN > 0) return 1;

/* If this point is reached, nothing is drawn: */
return 0;
}

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


