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

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

				bond_style4_quad2.c

Purpose:
	Draw bond which fits into quadrant 2 using style 4. See the file
	file bonds_style4.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 2 using style 4:===============================*/

int BondStyle4Quadrant2_ (Aux1S *aux1SP, int bondI)
{
long			pixels_drawnN = 0;
double			recip_denom, y_to_x_scale, y_to_z_scale;
int                     screen_x, line_screen_x, screen_y, screen_y1, delta_y;
double			d, atomic_z;
int			lineI;
size_t			pixelI;
NearestAtomS		*curr_pixelSP;
int			edge_x, rowI;
static int		edge_maskAA[5][2] =
				{{1, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 0}};

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

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

/* Vertical scan (top to bottom): */
screen_y1 = (aux1SP->screen_y0 + aux1SP->screen_y1) / 2;
for (screen_y = aux1SP->screen_y0; screen_y <= screen_y1; screen_y++)
	{
	/* Check is this pixel inside the area reserved for the */
	/* current image (there are two images in stereo mode): */
	if (screen_y < aux1SP->configSP->image_screen_y0) continue;
	if (screen_y > aux1SP->configSP->image_screen_y1) continue;

	/* Relative position: */
	delta_y = screen_y - aux1SP->screen_y0;

	/* Find the corresponding screen_x: */
	d = aux1SP->screen_x0 + y_to_x_scale * delta_y;
	screen_x = (int) (d + 0.5);

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

	/* Loop which draws lines (horizontal scan): */
	for (lineI = 0; lineI <= 6; lineI++)
		{
		/* Pixel position: */
		line_screen_x = screen_x +lineI - 3;

		/* Check is this pixel inside the area reserved for the */
		/* current image (there are two images in stereo mode): */
		if (line_screen_x <
			aux1SP->configSP->image_screen_x0[aux1SP->imageI])
			{
			continue;
			}
		if (line_screen_x > 
			aux1SP->configSP->image_screen_x1[aux1SP->imageI])
			{
			continue;
			}

		/* Current pixel index: */
		pixelI = aux1SP->guiSP->main_win_free_area_width * screen_y +
			 line_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],
			    line_screen_x, screen_y);

		/* Refresh the content of NearestAtomS */
		/* array  associated  with this pixel: */
		curr_pixelSP->styleI = 4;
		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 top end: */
edge_x  = aux1SP->screen_x0;
atomic_z = aux1SP->atomic_z0;
for (rowI = 0; rowI <= 1; rowI++)
	{
	/* Prepare and check screen_y: */
	screen_y = aux1SP->screen_y0 - rowI - 1;
	if (screen_y < aux1SP->configSP->image_screen_y0) continue;
	if (screen_y > aux1SP->configSP->image_screen_y1) continue;

	/* Vertical scan: */
	for (lineI = 0; lineI <= 4; lineI++)
		{
		/* Pixel x coordinate: */
		line_screen_x = edge_x + lineI - 2;

		/* Check line_screen_x: */
		if (line_screen_x <
			aux1SP->configSP->image_screen_x0[aux1SP->imageI])
			{
			continue;
			}
		if (line_screen_x >
			aux1SP->configSP->image_screen_x1[aux1SP->imageI])
			{
			continue;
			}

		/* Check the mask: */
		if (!edge_maskAA[lineI][rowI]) continue;

		/* Current pixel index: */
		pixelI = aux1SP->guiSP->main_win_free_area_width * screen_y +
			line_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],
			    line_screen_x, screen_y);

		/* Refresh the content of NearestAtomS */
		/* array  associated  with this pixel: */
		curr_pixelSP->styleI = 4;
		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++;
		}
	}

/* Rounding the bottom end: */
delta_y = screen_y1 - aux1SP->screen_y0;
d = (double) aux1SP->screen_x0 + y_to_x_scale * (double) delta_y;
edge_x = (int) (d + 0.5);
atomic_z = aux1SP->atomic_z0 + y_to_z_scale * (double) delta_y;
for (rowI = 0; rowI <= 1; rowI++)
	{
	/* Prepare and check screen_y: */
	screen_y = screen_y1 + rowI + 1;
	if (screen_y < aux1SP->configSP->image_screen_y0) continue;
	if (screen_y > aux1SP->configSP->image_screen_y1) continue;

	/* Vertical scan: */
	for (lineI = 0; lineI <= 4; lineI++)
		{
		/* Pixel x coordinate: */
		line_screen_x = edge_x + lineI - 2;

		/* Check line_screen_x: */
		if (line_screen_x <
			aux1SP->configSP->image_screen_x0[aux1SP->imageI])
			{
			continue;
			}
		if (line_screen_x >
			aux1SP->configSP->image_screen_x1[aux1SP->imageI])
			{
			continue;
			}

		/* Check the mask: */
		if (!edge_maskAA[lineI][rowI]) continue;

		/* Current pixel index: */
		pixelI = aux1SP->guiSP->main_win_free_area_width * screen_y +
			 line_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],
			    line_screen_x, screen_y);

		/* Refresh the content of NearestAtomS */
		/* array  associated  with this pixel: */
		curr_pixelSP->styleI = 4;
		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++;
		}
	}

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

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

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


