Ultrix-3.1/src/libplot/tla50/arc.c
/* 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);
}