#define LEFT_EDGE 0x1
#define RIGHT_EDGE 0x2
#define BOTTOM_EDGE 0x4
#define TOP_EDGE 0x8
#define INSIDE(a) (!a)
#define REJECT(a,b) (a&b)
#define ACCEPT(a,b) (!(a|b))
#define FALSE 0
#define TRUE 1
struct point2d
{
int x;
int y;
};
unsigned char encode(struct point2d pt,struct point2d winMin,struct point2d winMax)
{
unsigned char code=0x00;
if(pt.xwinMax.x)
code = code | RIGHT_EDGE;
if(pt.ywinMax.y)
code = code | TOP_EDGE;
return code;
}
void swapPts(struct point2d *p1,struct point2d *p2)
{
struct point2d tmp;
tmp=*p1;
*p1=*p2;
*p2=tmp;
}
void swapCodes(unsigned char *c1,unsigned char * c2)
{
unsigned char tmp;
tmp=*c1;
*c1=*c2;
*c2=tmp;
}
void clipLine(struct point2d winMin,struct point2d winMax,struct point2d p1,struct point2d p2)
{
unsigned char code1,code2;
int done=FALSE,draw=FALSE;
float m;
while(!done)
{
code1=encode(p1,winMin,winMax);
code2=encode(p2,winMin,winMax);
if(ACCEPT(code1,code2))
{
done=TRUE;
draw=TRUE;
}
else
{
if(REJECT(code1,code2))
{
done=TRUE;
}
else
{
if(INSIDE(code1))
{
swapPts(&p1,&p2);
swapCodes(&code1,&code2);
}
if(p2.x!=p1.x)
m=(float)(p2.y-p1.y)/(p2.x-p1.x);
if(code1 & LEFT_EDGE)
{
p1.y+=(winMin.x-p1.x)*m;
p1.x=winMin.x;
}
else
{
if(code1 & RIGHT_EDGE)
{
p1.y+=(winMax.x-p1.x)*m;
p1.x=winMax.x;
}
else
{
if(code1 & BOTTOM_EDGE)
{
if(p2.x!=p1.x)
p1.x+=(winMin.y-p1.y)/m;
p1.y=winMin.y;
}
else
{
if(code1 & TOP_EDGE)
{
if(p2.x!=p1.x)
p1.x+=(winMax.y-p1.y)/m;
p1.y=winMax.y;
}
}
}
}
}
}
}
if(draw)
line(p1.x,p1.y,p2.x,p2.y);
}