Sem 4‎ > ‎CG LAB‎ > ‎

P8: WAP to perform Line CLipping

posted Jan 25, 2012, 3:03 AM by Neil Mathew   [ updated Nov 3, 2012, 8:41 PM ]

What I learnt:
  • This algo fails where there is a vertical Line ( x=c ). I've made provisions for the Slope to be 1, rather than having the program crash due to division by zero. Even by specifying it as 1, the clipping is All Wrong. I get some strange diagonal within the clipping window when I should be getting a straight vertical line. 

    > Realized that making slope = 1 was a bad decision. It seemed rational at the time, but I see now that zero was needed. When the intersection is made on a Y axis based side, according to the algo, the difference between Y and Yaxis is multiplied by inverse of slope, in this case, zero.
    (Don't calculate Slope separately, write the expression as part of the statement. 
    Problem Solved)

  • This program implements Array Deletion, Tertiary operators and a manipulated Palindrome algo. This is there only because I chose to represent the 4-bit indicators as a long datatype rather than an int array. This was only possible because the 4-bit indicator is of the order 4321.


    Each Point indicated by four bit code: [ 4 3 2 1 ]
    (where the 4,3,2,1 will be either 0 or 1)



Correction:
(Later I realize I'm wrong. I've messed with convention.
What is explained as 4 3 2 1 should have been 1 2 3 4 .
That is, 1 if extends over top edge, 2 if it goes over bottom edge, etc)

SOURCE CODE:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
#include<graphics.h>
#include<iostream.h>
#include<conio.h>
 
int n; //No of Lines
 
int ClipWindow[2][2]; //Clipping Window Coordinates
/* For 2 vertices A and C, each having x and y coordinates*/
 
int Line[20][4];  //Line Coordinates
/* The 20 represents total number of lines possible
 4 represents the 4 coordinates required to draw ONE line */
 
void Draw()
{
clrscr();
 
int gdriver=DETECT,gmode;
initgraph(&gdriver, &gmode, "C:/TC/BGI");
 
setbkcolor(BLACK);
setcolor(WHITE);
for(int i=0; i<n; i++)
line(Line[i][0],Line[i][1],Line[i][2],Line[i][3]);
 
setcolor(CYAN);
rectangle(ClipWindow[0][0],ClipWindow[0][1]
                ,ClipWindow[1][0],ClipWindow[1][1]);
 
outtextxy(10,10, "Press any key to continue");
getch(); closegraph();
}
 
void UnClipped_Input()
{
cout<<"\n Enter the number of lines to draw : ";
cin>>n; cout<<endl;
 
for(int i=0; i<n; i++)
{
cout<<" LINE #"<<(i+1);
cout<<"\n Enter the Initial position (x,y) : ";
cin>>Line[i][0];
cin>>Line[i][1];
cout<<" Enter the Final position (x,y)   : ";
cin>>Line[i][2];
cin>>Line[i][3];
cout<<"\n";
}
cout<<"\n >> Enter the coordinates of the Clipping Window:";
cout<<"\n >> Vertex A (x,y) : ";
cin>>ClipWindow[0][0];
cin>>ClipWindow[0][1];
cout<<" >> Vertex C (x,y) : ";
cin>>ClipWindow[1][0];
cin>>ClipWindow[1][1];
}
long CheckBit(long x,long y)
{
long b=5; /* The 5 here is any random non zero number. 
This ensures 0000 doesn't become 0 */
int Xmax= 
ClipWindow[0][0] > ClipWindow[1][0] 
? ClipWindow[0][0] : ClipWindow[1][0];
 
int Xmin= 
ClipWindow[0][0] < ClipWindow[1][0] 
? ClipWindow[0][0] : ClipWindow[1][0];
int Ymax= 
ClipWindow[0][1] > ClipWindow[1][1] 
? ClipWindow[0][1] : ClipWindow[1][1];
 
int Ymin= 
ClipWindow[0][1] < ClipWindow[1][1] 
? ClipWindow[0][1] : ClipWindow[1][1];
 
//Case 4:
if(x < Xmin)
b=b*10 + 1;
else
b=b*10 + 0;
 
//Case 3:
if(x > Xmax)
b=b*10 + 1;
else
b=b*10 + 0;
 
//Case 2:
if(y < Ymin)
b=b*10 + 1;
else
b=b*10 + 0;
 
//Case 1:
if(y > Ymax)
b=b*10 + 1;
else
b=b*10 + 0;
 
return b;
}
 
long AND(long a, long b)
{
//Using manipulated Palindrome Algo
long c;
int digitA;
int digitB;
int digitC[4];
 
for(int i=3; i>=0; i--)
{
digitA=a%10;
digitB=b%10;
 
if( digitA==1 && digitB==1)
digitC[i]=1;
else
digitC[i]=0;
 
a/=10;
b/=10;
}
c=5;
for(i=0; i<4; i++)
c=(long) c*10+digitC[i];
 
return c;
}                       //END of AND function
 
void Clip()
{
int Xmax= 
ClipWindow[0][0] > ClipWindow[1][0] 
? ClipWindow[0][0] : ClipWindow[1][0];
 
int Xmin= 
ClipWindow[0][0] < ClipWindow[1][0] 
? ClipWindow[0][0] : ClipWindow[1][0];
 
int Ymax= 
ClipWindow[0][1] > ClipWindow[1][1] 
? ClipWindow[0][1] : ClipWindow[1][1];
 
int Ymin= 
ClipWindow[0][1] < ClipWindow[1][1] 
? ClipWindow[0][1] : ClipWindow[1][1];
 
long b1, b2, b1ANDb2;
int i,j,k;
int digit_b1, digit_b2;
double Slope;
 
for(i=0; i<n; i++)
{  //FOR EACH LINE:
 
b1=CheckBit(Line[i][0], Line[i][1]);
b2=CheckBit(Line[i][2], Line[i][3]);
b1ANDb2=AND(b1,b2);
 
if( b1ANDb2 != 50000 ) //OUTSIDE
{
//Remove OUTSIDE Line Coordinates from Array
 
for(int k=i; k<n-1; k++)
{
Line[k][0]=Line[k+1][0];
Line[k][1]=Line[k+1][1];
Line[k][2]=Line[k+1][2];
Line[k][3]=Line[k+1][3];
}
n--;
i--;
 
}
 
else  //INSIDE
{
 
        //Completely Inside
        if( b1==50000 && b2==50000 )
        {
        //No Change to be made to Line Coordinates.
        }
 
 
        //Partially Inside Cases
        else if( b1!=50000 || b2!=50000 )
        {
 
        if( (Line[i][2] - Line[i][0]) == 0)
        Slope= 1.0;
        else
        Slope= 
        (double) ((Line[i][3]-Line[i][1])/(Line[i][2]-Line[i][0]));
 
 
         for(j=1; j<=4; j++)
         {
         digit_b1=b1%10;
         digit_b2=b2%10;
 
         switch(j)
         {
 
         case 1:
 
         if(digit_b1==1)
         {
         Line[i][0]= Line[i][0] + ( (Ymax - Line[i][1]) / Slope );
         Line[i][1]=Ymax;
         }
         else if(digit_b2==1)
         {
         Line[i][2]= Line[i][2] + ( (Ymax - Line[i][3] ) / Slope );
         Line[i][3]=Ymax;
         }
         break;
 
         case 2:
 
         if(digit_b1==1)
         {
         Line[i][0]= Line[i][0] + ( (Ymin - Line[i][1] ) / Slope );
         Line[i][1]=Ymin;
         }
         else if(digit_b2==1)
         {
         Line[i][2]= Line[i][2] + ( (Ymin - Line[i][3] ) / Slope );
         Line[i][3]=Ymin;
         }
         break;
 
         case 3:
 
         if(digit_b1==1)
         {
         Line[i][1]= Line[i][1] + ( ( Xmax - Line[i][0] ) * Slope) ;
         Line[i][0]=Xmax;
         }
         else if(digit_b2==1)
         {
         Line[i][3]= Line[i][3] + ( (Xmax - Line[i][2] ) * Slope) ;
         Line[i][2]=Xmax;
         }
         break;
 
         case 4:
 
         if(digit_b1==1)
         {
         Line[i][1]= Line[i][1] + ( (Xmin - Line[i][0] ) * Slope) ;
         Line[i][0]=Xmin;
         }
         else if(digit_b2==1)
         {
         Line[i][3]= Line[i][3] + ( (Xmin - Line[i][2] ) * Slope) ;
         Line[i][2]=Xmin;
         }
         break;
 
         } //End of Case
 
 
         b1/=10;
         b2/=10;
 
      } //End of inner For Loop
 
 
      b1=CheckBit(Line[i][0],Line[i][1]);
      b2=CheckBit(Line[i][2],Line[i][3]);
      b1ANDb2=AND(b1,b2);
 
 
      if( b1!=50000 || b2!=50000 )
      { i--; continue; }
 
 
} //End of Inner If-Else-if
} //End of Outer If-Else-if
} //End of Outer For Loop
}
 
 
void main()
{
clrscr();
 
UnClipped_Input();
Draw();
 
Clip();
Draw();
}


OUTPUT:







ċ
Neil Mathew,
Jan 25, 2012, 3:19 AM
Comments