Ultrix-3.1/src/libplot/tla50/arc.c

Compare this file to the similar file:
Show the results in this format:

/* SCCSID: @(#)arc.c	3.0	4/22/86 */

/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

/*
	The circle algorithm used here is that due to J. Michener

	xi is the x coordinate of the centre.
	yi is the y coordinate of the centre.
	radius is radius
*/

#include <stdio.h>
#define DEBUG 0
#define DEBUG2 0
#define X 0
#define Y 1
extern float scalex,scaley,botx,boty,obotx,oboty;
float factor;
float sc_xobot, sc_yobot;
float start[2] [9], aend[2] [9];
int drw_oct[9];
arc(xi,yi,x0,y0,x1,y1)
int	xi,yi,x0,y0,x1,y1;
{
	int	x,y,ox,oy,oyx,d,xradius,arc_points(),octant();
	int	st_x,st_y,en_x,en_y,st_oct,en_oct;
	/* The arrays start and end points for the arc of each octant of the
	   possible circle. The arrays are dimensioned as 2 x 9, when
	   2 x 8 would suffice. This is so that the column number corresponds
	   to the octant number  */
	int value;
	float dx,dy;
	double radius,limit,sqrt();
#if DEBUG
	fprintf(stderr,"Arc called with centre xi,yi = %d,%d\n",xi,yi);
	fprintf(stderr,"Arc starts at x0,y0 = %d,%d\n",x0,y0);
	fprintf(stderr,"Arc ends at x1,y1 = %d,%d\n",x1,y1);
#endif
	factor = scaley / scalex;
	/* initalize the arrays  - use value as a temporary variable */
	for (value = 0; value <= 9; value++)
		 start[X] [value] = start[Y] [value] = aend[X] [value]
				  = aend[Y] [value] = drw_oct[value] = 0.0;
	value = 4;
	/* Calculate the radius */

	dx = xi - x0;
	dy = yi - y0;
	radius = sqrt(dx * dx + dy * dy);
	xradius = radius * scalex;	/* the radius on the x space */
	ox = xi * scalex;		/* the x coord of the centre in x */
	oyx = yi * scalex;		/* the y coord of the centre in x */
#ifdef	DEBUG
	oy = yi * scaley;		/* the y coord of the centre in y */
#endif

	/* now patch in the arc start and end ... */
	st_x = x0 * scalex;		/* the start x coord in the x scale */
	st_y = y0 * scalex;		/* start y coord in the x scale */
	en_x = x1 * scalex;		/* end x coord in the x scale */
	en_y = y1 * scalex;		/* end y coord in the x scale */
	st_oct = octant(ox,oyx,st_x,st_y); /* start octant of the arc */
	en_oct = octant(ox,oyx,en_x,en_y); /* end octant of the arc */
	/* now initialise some elements of start and end - others are
	   always zero. */

	limit = xradius / sqrt(2.0);	 /* the point at which x = y */
	start[X][1] = start[Y][2] = start[Y][3] = start[X][8] = (int) xradius;

	aend[X][1]  = aend[Y][1] = aend[X][2] = aend[Y][2] = aend[Y][3]
		    = aend[X][7] = aend[Y][4] = aend[X][8] = (int) limit;

	aend[X][3]  = aend[X][4] = aend[X][5] = aend[Y][5] = aend[X][6]
		    = aend[Y][6] = aend[Y][7] = aend[Y][8] = (int) -limit;


	start[X][4] = start[X][5] = start[Y][6] = start[Y][7] = (int) -xradius;


#if DEBUG
	fprintf(stderr,"centre in x is ox,oyx = %d,%d \n",ox,oyx);
	fprintf(stderr,"st_x,st_y  is %d,%d  \n",st_x,st_y);
	fprintf(stderr,"x0,y0 is %d,%d	 \n",x0,y0);
	fprintf(stderr,"en_x,en_y  is %d,%d  \n",en_x,en_y);
	fprintf(stderr,"x1,y1 is %d,%d \n",x1,y1);
	fprintf(stderr,"st_oct is %d, en_oct is %d \n",st_oct,en_oct);
#endif
	if ( st_oct == 2.0 * (int) ( st_oct / 2.0 ) )
			/* start octant is 'even' */
			{
#if DEBUG
			fprintf(stderr,"start octant is even \n");
#endif
			aend[X][st_oct] = st_x - ox;
			aend[Y][st_oct] = st_y - oyx;
			}
	else
			/* start octant is 'odd' */
			{
#if DEBUG
			fprintf(stderr,"start octant is odd \n");
#endif
			start[X][st_oct] = st_x - ox;
			start[Y][st_oct] = st_y - oyx;
			}

	if ( en_oct == 2.0 * (int) ( en_oct / 2.0 ) )
			/* end octant is 'even' */
			{
#if DEBUG
			fprintf(stderr,"end octant is even\n");
#endif
			start[X][en_oct] = en_x - ox;
			start[Y][en_oct] = en_y - oyx;
			}
	else
			/* end octant is 'odd' */
			{
#if DEBUG
			fprintf(stderr,"end octant is odd\n");
#endif
			aend[X][en_oct] = en_x - ox;
			aend[Y][en_oct] = en_y - oyx;
			}
#define min(A,B) ( (A < B) ? A : B )

	if ( st_oct < en_oct )
		for ( value = st_oct; value <= min(en_oct,8); value++)
			drw_oct[value] = 1;
	else
		{
		for ( value = st_oct; value <= 8; value++)
			drw_oct[value] = 1;
		for ( value = 1; value <= en_oct; value++)
			drw_oct[value] = 1;
		}
#if DEBUG
	for (value = 1; value <9;value++)
	  {
	  fprintf(stderr,"start[X][%d],[Y][%d] is %f,%f \n",value,value,
			  start[X][value],start[Y][value]);

	  fprintf(stderr,"aend[X][%d],[Y][%d] is %f, %f \n",value,value,
			  aend[X][value],aend[Y][value]);

	  fprintf(stderr,"drw_oct[%d] is %d \n",value,drw_oct[value]);
	  }
#endif
	sc_xobot = obotx * scalex;	/* the origin of the window in x */
	sc_yobot = oboty * scaley;
#if DEBUG
    fprintf(stderr,"sc_xobot is %f, sc_yobot is %f \n",sc_xobot,sc_yobot);
#endif
	y = xradius ;
	d = 3 - 2 * xradius ;
#if DEBUG
	fprintf(stderr,"xradius = %d\n",xradius);
	fprintf(stderr,"ox = %d, oy = %d , y = xradius\n",ox,oy);
#endif
	x = 0 ;

	while( x < y )
		{
		arc_points(x,y,ox,oyx,value) ;
		if ( d < 0 )
			d += 4 * x + 6 ;
		else
			{
			d += 4 * ( x - y ) + 10 ;
			y-- ;
			}
		x++ ;
		} /* end while */

	if( x == y )
		arc_points(x,y,ox,oyx,value) ;
}

#ifdef DEBUG2
arc_points(x,y,ox,oyx,value)
#else
arc_points( x, y, ox, oyx )
#endif
register int	x,y,	      /* x and y coordinates of the point */
		ox,oyx; 	 /* x and y coordinates of the centre */


#ifdef DEBUG2
int value;
#endif

{
	extern float factor;
	int setbit(),xcoord(),ycoord(),px,py,mx,my,xtemp,ytemp;
#if DEBUG2
	fprintf(stderr,"arcpoints(%d,%d,%d)\n",x,y,value);  /*DEBUG*/
#endif
#define X_coord(A)     (A + xtemp)
#define Y_coord(A)     (ytemp + ( ( A + oyx )  * factor))
	xtemp = botx - sc_xobot + ox;
	ytemp = boty - sc_yobot;
	px = X_coord(x);
	py = Y_coord(y);
	mx = X_coord(-x);
	my = Y_coord(-y);

	/* now for each possible octant we test to see if we need to draw
	   the arc for that octant */

	if (( drw_oct[2] > 0 && x >= start[X][2] &&  x <= aend[X][2]
		  && y <= start[Y][2] && y >= aend[Y][2]))
		  setbit(px,py);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 2\n",x,y);
#endif
	if (( drw_oct[7] > 0 && x >= start[X][7] && x <= aend[X][7]
		  && -y >= start[Y][7] && -y <= aend[Y][7]))
		  setbit(px,my);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 7\n",x,-y);
#endif
	if (( drw_oct[6] > 0 && -x <= start[X][6] && -x >= aend[X][6]
		  && -y >= start[Y][6] && -y <= aend[Y][6]))
		  setbit(mx,my);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 6\n",-x,-y);
#endif
	if ( drw_oct[3] > 0 && start[X][3] >= -x && -x >= aend[X][3] &&
		  start[Y][3] >= y && y >= aend[Y][3])
		  setbit(mx,py);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 3\n",-x,y);
#endif
	px = Y_coord(x);
	py = X_coord(y);
	mx = Y_coord(-x);
	my = X_coord(-y);

	if ( drw_oct[1] > 0 && y <= start[X][1] && y >= aend[X][1] &&
		  x >= start[Y][1] && x <= aend[Y][1])
		  setbit(py,px);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 1\n",y,x);
#endif
	if ( drw_oct[8] > 0 && y <= start[X][8] && y >= aend[X][8] &&
		  -x <= start[Y][8] && -x >= aend[Y][8])
		  setbit(py,mx);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 8\n",y,-x);
#endif
	if ( drw_oct[5] > 0 && -y >= start[X][5] && -y <= aend[X][5] &&
		  -x <= start[Y][5] && -x >= aend[Y][5])
		  setbit(my,mx);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 5\n",-y,-x);
#endif
	if ( drw_oct[4] > 0 && -y >= start[X][4] && -y <= aend[X][4] &&
		  x >= start[Y][4] && x <= aend[Y][4])
		  setbit(my,px);
#if DEBUG2
	else
		fprintf(stderr," %d,%d not for octant 4\n",-y,x);
#endif
}

octant(x,y,xp,yp)

int x,y,xp,yp;

/* This function returns a number indicating the octant of the circle
   centre (x,y) contains the point (xp,yp)

*/

{
#if DEBUG
	fprintf(stderr,"Octant,centre is x,y = %d,%d,point is xp,yp= %d,%d\n",
			x,y,xp,yp);
#endif

	if ( x <= xp )

		/* x is positive */

		if ( y <= yp )

			/* y is positive */
			if ( xp >= yp )
				return(1);
			else
				return(2);
		else

			/* y is negative */

			if ( -yp >= xp )
				return(7);
			else
				return(8);
	else
		/* x is negative */

		if ( y <= yp )

			/* y is positive */
			if ( -xp >= yp )
				return(4);
			else
				return(3);
		else

			/* y is negative */

			if ( -yp >= -xp )
				return(6);
			else
				return(5);
}