/*
THIS IS A C PROGRAM THAT DEMONSTRATES REGULAR 2D LINE CLIPPING BY EXPLICIT METHOD
*/
#include<stdlib.h>
#include<conio.h>
#include<graphics.h>
#include<math.h>
enum visibility {TOTALLY_VISIBLE,TRIVIALLY_INVISIBLE,PARTLY_VISIBLE,ONE_SIDE_INTERSECTION,TWO_SIDE_INTERSECTIONS};
struct line_structure {
int x1, y1, x2, y2; /* defining co-ordinates of the endpoints (x1,y1) and (x2,y2) */
short int endpointcode1[4], endpointcode2[4]; /* defining end point codes of each of the end points */
enum visibility v; /* v depends on BITWISEAND of end point codes of first & second points */
};
typedef struct line_structure linein2d;
/* global variables */
int L, R, T, B;
/* Simple function to calculate the end point codes of the end points of a line and to check if
it is partially or completely visible or invisible and add it as a line in an array at the desired position */
int addline(int abs1, int ord1, int abs2, int ord2, linein2d array[],int length)
{
int i; /* i is a loop counter */
short int sum1, sum2; /* sum1, sum2 are the sum of the bits of the 2 end point codes */
sum1 = sum2 = 0;
array[length].x1 = abs1; array[length].y1 = ord1;
array[length].x2 = abs2; array[length].y2 = ord2;
/* forming the end point code of the first point */
if(abs1<L)
array[length].endpointcode1[0]=1;
else
array[length].endpointcode1[0]=0;
if(abs1>R)
array[length].endpointcode1[1]=1;
else
array[length].endpointcode1[1]=0;
if(ord1<B)
array[length].endpointcode1[2]=1;
else
array[length].endpointcode1[2]=0;
if(ord1>T)
array[length].endpointcode1[3]=1;
else
array[length].endpointcode1[3]=0;
sum1=array[length].endpointcode1[0]+array[length].endpointcode1[1]+array[length].endpointcode1[2]
+array[length].endpointcode1[3];
/* forming the end point code of the second point */
if(abs2<L)
array[length].endpointcode2[0]=1;
else
array[length].endpointcode2[0]=0;
if(abs2>R)
array[length].endpointcode2[1]=1;
else
array[length].endpointcode2[1]=0;
if(ord2<B)
array[length].endpointcode2[2]=1;
else
array[length].endpointcode2[2]=0;
if(ord2>T)
array[length].endpointcode2[3]=1;
else
array[length].endpointcode2[3]=0;
sum2=array[length].endpointcode2[0]+array[length].endpointcode2[1]+array[length].endpointcode2[2]
+array[length].endpointcode2[3];
/* checking if it is trivially invisible */
for(i=0;i<4;i++)
if(array[length].endpointcode1[i]==array[length].endpointcode2[i] && array[length].endpointcode1[i]==1)
{
array[length].v = TRIVIALLY_INVISIBLE;
return 0;
}
/* checking if it is totally visible or partially visible. If partially visible, then
how many intersections of the line with the regular window occur */
if(sum1==0 && sum2==0)
array[length].v = TOTALLY_VISIBLE;
else if(sum1==0 || sum2==0)
array[length].v = ONE_SIDE_INTERSECTION;
else
array[length].v = TWO_SIDE_INTERSECTIONS;
return 1;
}
/* simple function to draw an equivalent line in ANSI C when the endpoints are described in rectangular
X-Y coordinate system */
void linejoin(int x1, int y1, int x2, int y2)
{
int SCALE_FACTOR = 1;
int X_SHIFT = getmaxx()/2;
int Y_SHIFT = getmaxy()/2;
int newx1 = x1*SCALE_FACTOR + X_SHIFT ;
int newy1 = -y1*SCALE_FACTOR + Y_SHIFT ;
int newx2 = x2*SCALE_FACTOR + X_SHIFT ;
int newy2 = -y2*SCALE_FACTOR + Y_SHIFT ;
line(newx1, newy1, newx2, newy2);
}
/* simple function to draw the clipping region before actually clipping the scene */
void drawclippingregion()
{
int SCALE_FACTOR = 1;
int X_SHIFT = getmaxx()/2;
int Y_SHIFT = getmaxy()/2;
int newL = L*SCALE_FACTOR + X_SHIFT ;
int newB = -B*SCALE_FACTOR + Y_SHIFT ;
int newR = R*SCALE_FACTOR + X_SHIFT ;
int newT = -T*SCALE_FACTOR + Y_SHIFT ;
moveto(newL, newT);
lineto(newR, newT);
lineto(newR, newB);
lineto(newL, newB);
lineto(newL, newT);
}
/* A function that draws partially visible lines which intersects regular window only once */
void clipping1(linein2d t)
{
int i, newx1, newy1, newx2, newy2;
short int flag=0;
double m;
/* identifying which end point is inside the clipping region
and its coordinates are assigned to newx1 and newy1 */
for(i=0;i<4;i++)
if(t.endpointcode1[i]!=0)
break;
if(i==4) {
newx1 = t.x1;
newy1 = t.y1;
}
else {
newx1 = t.x2;
newy1 = t.y2;
}
/* when the line is vertical */
if(t.x1==t.x2) {
newx2 = newx1;
if(t.endpointcode1[2]==1 || t.endpointcode2[2]==1)
newy2 = B;
else
newy2 = T;
}
/* when the line is horizontal */
else if(t.y1==t.y2)
{
newy2 = newy1;
if(t.endpointcode1[0]==1 || t.endpointcode2[0]==1)
newx2 = L;
else
newx2 = R;
}
else
{
m = (double) (t.y2-t.y1)/(t.x2-t.x1); /* slope of the line is m */
/* when the line intersects the left edge of the window */
if(t.endpointcode1[0]^t.endpointcode2[0]==1)
{
newx2 = L;
newy2 = m*(newx2-newx1) + newy1;
if(newy2>=B && newy2<=T)
flag=1;
}
/* when the line intersects the right edge of the window */
if(t.endpointcode1[1]^t.endpointcode2[1]==1 && flag==0)
{
newx2 = R;
newy2 = m*(newx2-newx1) + newy1;
if(newy2>=B && newy2<=T)
flag=1;
}
/* when the line intersects the bottom edge of the window */
if(t.endpointcode1[2]^t.endpointcode2[2]==1 && flag==0)
{
newy2 = B;
newx2 = newx1 +(double) (newy2-newy1)/m;
if(newx2>=L && newx2<=R)
flag=1;
}
/* when the line intersects the top edge of the window */
if(flag==0)
{
newy2 = T;
newx2 = newx1 + (newy2-newy1)/m;
}
}
linejoin(newx1,newy1,newx2,newy2); /* draw the line */
}
/* A function that draws partially visible lines which intersects regular window twice */
void clipping2(linein2d t)
{
int newx1, newy1, newx2, newy2, tempxL, tempyL, tempxR, tempyR, tempxB, tempyB, tempxT, tempyT;
short int flag = 0;
double m;
/* when the line is vertical */
if(t.x1==t.x2)
{
newx1 = newx2 = t.x1;
newy1 = B;
newy2 = T;
}
/* when the line is horizontal */
else if(t.y1==t.y2)
{
newy1 = newy2 = t.y1;
newx1 = L;
newx2 = R;
}
else
{
m = (double)(t.y2-t.y1)/(t.x2-t.x1) ;
/* considering intersection point of the line segment with the left edge */
{
tempxL = L;
tempyL = t.y1 + m*(tempxL - t.x1);
if(tempyL>=B && tempyL<=T)
{
flag++;
newx1 = tempxL;
newy1 = tempyL;
}
}
/* considering intersection point of the line segment with the right edge */
{
tempxR = R;
tempyR = t.y1 + m*(tempxR - t.x1);
if(tempyR>=B && tempyR<=T)
{
if(flag)
{
newx2 = tempxR;
newy2 = tempyR;
flag++;
}
else
{
newx1 = tempxR;
newy1 = tempyR;
flag++;
}
}
}
/* considering intersection of the line segment with the bottom edge */
if(flag<2)
{
tempyB = B;
tempxB = t.x1 + (tempyB - t.y1)/m;
if(tempxB>=L && tempxB<=R)
{
if(flag)
{
newx2 = tempxB;
newy2 = tempyB;
flag++;
}
else
{
newx1 = tempxB;
newy1 = tempyB;
flag++;
}
}
}
/* considering intersection of the line segment with the top edge */
if(flag<2)
{
newy2 = T;
newx2 = t.x1 + (newy2 - t.y1)/m;
flag++;
}
}
if(flag==2)
linejoin(newx1,newy1,newx2,newy2);
}
/* A function for drawing only the totally visible or partially visible lines */
void drawclippedlines(linein2d array[], int size)
{
int loopcounter;
for(loopcounter=0;loopcounter<size;loopcounter++)
if(array[loopcounter].v==TOTALLY_VISIBLE)
linejoin(array[loopcounter].x1,array[loopcounter].y1,array[loopcounter].x2,array[loopcounter].y2);
else if(array[loopcounter].v==ONE_SIDE_INTERSECTION)
clipping1(array[loopcounter]);
else if(array[loopcounter].v==TWO_SIDE_INTERSECTIONS)
clipping2(array[loopcounter]);
}
int main(void)
{
int gdriver = DETECT, gmode, errorcode; /* request auto detection */
/* declaring variables */
int length, i, x1, y1, x2, y2;
linein2d arr[10];
/* accepting a 2d scene comprising of line segments only and defining a clipping region */
printf("\t\t *** REGULAR 2D CLIPPING ***\n");
printf("\nNow enter the extremities of the clipping region in the format (left, right, bottom, top):\n");
scanf("%d%d%d%d",&L,&R,&B,&T);
printf("\nHow many line segments to be provided: ");
scanf("%d",&length);
printf("\nKeep entering the end points of the lines..............\n");
for(i=0; i<length; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
addline(x1,y1,x2,y2,arr,i);
}
/* initialize graphics and local variables */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk)
/* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* terminate with an error code */
}
/* clearing device */
cleardevice();
setbkcolor(WHITE);
/* draw scene comprising of */
setcolor(BLACK);
for(i=0;i<length;i++)
linejoin(arr[i].x1,arr[i].y1,arr[i].x2,arr[i].y2);
/* draw clipping region in green dashed style */
setlinestyle(DASHED_LINE,1,1);
setcolor(DARKGRAY);
drawclippingregion();
getch(); /* wait till a kep is pressed */
cleardevice(); /* clear device */
setbkcolor(WHITE);
setlinestyle(SOLID_LINE,1,1);
/* Now drawing clipping region again */
setlinestyle(DASHED_LINE,1,1);
setcolor(DARKGRAY);
drawclippingregion();
setlinestyle(SOLID_LINE,1,1);
setcolor(BLACK);
drawclippedlines(arr,length);
getch();
return 0;
}
/*
THIS IS A C PROGRAM THAT DEMONSTRATES REGULAR 2D LINE CLIPPING BY COHEN-SUTHERLAND ALGORITHM
*/
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<conio.h>
#include<dos.h>
#include<math.h>
const int LEFT = 1; /*0001*/
const int RIGHT = 2; /*0010*/
const int BOTTOM = 4; /*0100*/
const int TOP = 8; /*1000*/
typedef struct point{
float x;
float y;
}point;
void drawLine(point[]);
int computeOutCode(point,int,int,int,int);
void SutherlandCohenLineClipper(point,point,int,int,int,int);
void main(){
int gdriver=DETECT,gmode,gerror;
int temp;
point P[20][2]; /*total 20 pairs of end-points */
int midx,midy;
int xl,xr,yb,yt,i,n=10;
float x0,y0,x1,y1;
char c[30];
initgraph(&gdriver,&gmode,"C:\\TC\\bgi");
gerror = graphresult();
if (gerror != grOk){ /* an error occurred*/
printf("Graphics error: %s\n", grapherrormsg(gerror));
printf("Press any key to halt:");
getch();
exit(1); /* terminate with an error code*/
}
printf("\nEnter the boundaries of the window as(xL,xR,yB,yT) ");
scanf("%d%d%d%d",&xl,&xr,&yb,&yt);
printf("\nHow many lines in the figure? ");
scanf("%d",&n);
randomize();
for(i=0;i<n;i++)
{
temp = rand()%15;
P[i][0].x=temp;
temp = rand()%15;
P[i][0].y=temp;
temp = rand()%15;
P[i][1].x=temp;
temp = rand()%15;
P[i][1].y=y1;
}
midx = getmaxx()/2;
midy = getmaxy()/2;
cleardevice();
setbkcolor(WHITE);
setlinestyle(DASHED_LINE,1,1);
setcolor(DARKGRAY);
rectangle(midx+xl*unitx,midy-yt*unity,midx+xr*unitx,midy-yb*unity); /* drawing clipping region */
/* drawing original lines */
setlinestyle(SOLID_LINE,1,1);
setcolor(BLACK);
for(i=0;i<n;i++) {
line(midx+unitx*P[i][0].x,midy-unity*P[i][0].y,midx+unitx*P[i][1].x,midy-unity*P[i][1].y);
getch(); /* wait after original line draw */
}
cleardevice();
setbkcolor(WHITE);
setlinestyle(DASHED_LINE,1,1);
setcolor(DARKGRAY);
rectangle(midx+xl*unitx,midy-yt*unity,midx+xr*unitx,midy-yb*unity); /* redrawing clipping region */
/* drawing clipped lines */
setlinestyle(SOLID_LINE,1,1);
setcolor(BLACK);
for(i=0;i<n;i++)
SutherlandCohenLineClipper(P[i][0],P[i][1],xl,xr,yb,yt);
getch();
closegraph();
}
void SutherlandCohenLineClipper (point P0,point P1,int xl,int xr,int yb,int yt){
int outcode0,outcode1,outcodeout;
int done,accept;
int found;
float m,x,y;
point P[2];
/*initialize values*/
m = (P1.y-P0.y)/(P1.x-P0.x); /*slope*/
outcode0 = computeOutCode(P0,xl,xr,yb,yt);
outcode1 = computeOutCode(P1,xl,xr,yb,yt);
done = 0;
accept = 0; /*acts as boolean flags*/
do{
if(!(outcode0 | outcode1)){ /*if true, totally visible*/
done = 1;
accept = 1;
}
else if(outcode0 & outcode1){ /*if true, totally invisible*/
done = 1;
}
else{ /*if true, partially visible*/
if(outcode0); /*if true, P0 outside, NO SWAP*/
else{ /*P1 outside, SWAP*/
point temp;
temp = P0;
P0 = P1;
P1 = temp;
outcodeout = outcode1;
outcode1 = outcode0;
outcode0 = outcodeout;
}
found=0;
if(outcode0 & TOP){ /*split line at top edge*/
x = P0.x + (yt-P0.y)/m;
y = yt;
if(x>=xl && x<=xr)
found=1;
}
else if(outcode0 & BOTTOM){ /*split line at bottom edge*/
x = P0.x + (yb-P0.y)/m;
y = yb;
if(x>=xl && x<=xr)
found=1;
}
if((outcode0 & RIGHT) && found==0){ /*split at right edge*/
y = P0.y + (xr-P0.x)*m;
x = xr;
if(y>=yb && y<=yt)
found=1;
}
else if(found==0){
y = P0.y + (xl-P0.x)*m;
x = xl;
found=1;
}
P0.x = x;
P0.y = y;
outcode0 = computeOutCode(P0,xl,xr,yb,yt);
}
}while(!done);
if(accept){
P[0] = P0; P[1] = P1;
drawLine(P);
}
getch();
}
/*Compute the bit code for a point (x, y) using the clip rectangle
bounded diagonally by (xl, yb), and (xr, yt)*/
int computeOutCode (point P,int xl,int xr,int yb,int yt){ /* ok */
int code = 0;
if (P.y > yt) /*above the clip window*/
code |= TOP;
else if (P.y < yb) /*below the clip window*/
code |= BOTTOM;
if (P.x > xr) /*to the right of clip window*/
code |= RIGHT;
else if (P.x < xl) /*to the left of clip window*/
code |= LEFT;
return code;
}
void drawLine(point P[]){ /* draws a line with floating point coordinates */
int x0,y0,x1,y1,midx,midy;
float ft;
int it;
int unitx_sd = unitx/10;
int unity_sd = unity/10;
char c[30];
it = (int)P[0].x; ft = (P[0].x-it)*10;
x0 = it*unitx+ft*unitx_sd;
it = (int)P[0].y; ft = (P[0].y-it)*10;
y0 = it*unity+ft*unity_sd;
it = (int)P[1].x; ft = (P[1].x-it)*10;
x1 = it*unitx+ft*unitx_sd;
it = (int)P[1].y; ft = (P[1].y-it)*10;
y1 = it*unity+ft*unity_sd;
midx = getmaxx()/2;
midy = getmaxy()/2;
line(midx+x0,midy-y0,midx+x1,midy-y1);
}
/*
THIS IS A C PROGRAM THAT DEMONSTRATES REGULAR 2D LINE CLIPPING BY CYRUS-BECK ALGORITHM
*/
#include<stdio.h>
#include<conio.h>
#include<graphics.h>
#include<stdlib.h>
#include<dos.h>
/*Position vector*/
typedef struct
{
int x,y;
}Vector;
typedef int * Window;
Window w=(int *)malloc(4*sizeof(int));
/*function prototypes*/
void Cyrus_Beck(Vector,Vector,Vector *,Vector *,int);
int Dot_Product(Vector *,Vector *);
void main()
{
int driver = DETECT,mode,xleft,xright,ybottom,ytop;
Vector P1,P2;
Vector f_i[4],n_i[4];
initgraph(&driver,&mode,"c:\\tc\\bgi");
clrscr();
printf("\nEnter the window in the form x_l,x_r,y_b,y_t\n");
scanf("%d%d%d%d",&w[0],&w[1],&w[2],&w[3]);
xleft=w[0];
xright=w[1];
ybottom=w[2];
ytop=w[3];
printf("\nEnter the first point\n");
scanf("%d%d",&P1.x,&P1.y);
printf("\nEnter the second point\n");
scanf("%d%d",&P2.x,&P2.y);
clrscr();
/*calculate the edge points*/
f_i[0].x=xleft;
f_i[0].y=ytop;
f_i[1].x=xright;
f_i[1].y=ybottom;
f_i[2].x=xleft;
f_i[2].y=ybottom;
f_i[3].x=xright;
f_i[3].y=ytop;
/*the inner normal unit vectors*/
n_i[0].x=1;
n_i[0].y=0;
n_i[1].x=-1;
n_i[1].y=0;
n_i[2].x=0;
n_i[2].y=1;
n_i[3].x=0;
n_i[3].y=-1;
cleardevice();
setbkcolor(WHITE);
/*drawing the window*/
setlinestyle(DASHED_LINE,1,1);
setcolor(DARKGRAY);
line(320+xleft,240-ytop,320+xleft,240-ybottom);
line(320+xright,240-ytop,320+xright,240-ybottom);
line(320+xleft,240-ytop,320+xright,240-ytop);
line(320+xleft,240-ybottom,320+xright,240-ybottom);
/*drawing the original line*/
setlinestyle(SOLID_LINE,1,1);
setcolor(BLACK);
line(320+P1.x,240-P1.y,320+P2.x,240-P2.y);
getch();
cleardevice();
setbkcolor(WHITE);
/*redrawing the window*/
setlinestyle(DASHED_LINE,1,1);
setcolor(DARKGRAY);
line(320+xleft,240-ytop,320+xleft,240-ybottom);
line(320+xright,240-ytop,320+xright,240-ybottom);
line(320+xleft,240-ytop,320+xright,240-ytop);
line(320+xleft,240-ybottom,320+xright,240-ybottom);
/*showing the clipped line*/
setlinestyle(SOLID_LINE,1,1);
setcolor(BLACK);
Cyrus_Beck(P1,P2,n_i,f_i,4);
getch();
closegraph();
}
/*routine to implement the Cyrus Beck algorithm*/
void Cyrus_Beck(Vector P1,Vector P2,Vector *n_i,Vector *f_i,int k)
{
/*
P1 and P2 are the end points of the line
the no. of edges for the clipping region is k
the n_i are the k normal vectors
the f_i are the k boundary points,one in each edge
D is the direction of the line,P2-P1
w_i is the weighting function,P1-f_i
tL,tV are the lower and upper parameter limits
*/
Vector D,w_i;
float t,tL,tU;
float Ddotn,Wdotn;
int i;
/*initialize the parameter limits, assuming entire line is visible*/
tL=0.0;
tU=1.0;
D.x=P2.x-P1.x;
D.y=P2.y-P1.y;
for(i=1;i<=k;i++)
{
/* calculate w_i,D.n_i and w_i.n_i for this value of I */
w_i.x=P1.x-f_i[i-1].x;
w_i.y=P1.y-f_i[i-1].y;
Ddotn=Dot_Product(&D,&n_i[i-1])*1.0;
Wdotn=Dot_Product(&w_i,&n_i[i-1])*1.0;
if(Ddotn!=0.0)
{
t=(-1.0)*Wdotn/(float)Ddotn;
/*looking for the lower or upper limit? */
if(Ddotn>0)
{
/*looking for the lower limit is t within [0,1] */
if(t>1.0) /*region entirely to the right,trivially invisible*/
{
printf("\nLine trivially invisible1 %f\n",t);
return;
}
else
tL=(t>=tL)?t:tL;
}
else /*at this point Ddotn<0*/
{
/* looking for the upper limit,is t within [0,1] */
if(t<0.0)
/* region entirely to the left, trivially invisible */
{
printf("\nLine trivially invisible2 %f\n",t);
return;
}
else
tU=(t<=tU)?t:tU;
}
} /* end if */
else /* here Ddotn=0 */
if(Wdotn<0)
{
/* the line is trivially invisible or an invisible point
abnormal exit from routine */
printf("\nLine trivially invisible or invisible point\n");
return;
}
}
/*a normal exit from loop has occurred
check if the line is in fact invisible*/
if(tL<=tU)
{
line(320+P1.x+(P2.x-P1.x)*tL,240-P1.y-(P2.y-P1.y)*tL,320+P1.x+(P2.x-P1.x)*tU,240-P1.y-(P2.y-P1.y)*tU);
return;
}
}
/* subroutine to calculate the Dot product of 2 vectors */
int Dot_Product(Vector *V1,Vector *V2)
{
return (V1->x*V2->x+V1->y*V2->y);
}
No comments:
Post a Comment
Do you think this information useful or was not up to the mark? Comment if you have any advices or suggestions about the post.