Jspice3
mfbclip.c
Go to the documentation of this file.
1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: -C- 1982 Giles Billingsley
4 **********/
5 /*
6  * mfbclip.c
7  *
8  * sccsid "@(#)mfbclip.c 1.9 9/3/83"
9  *
10  * MFB is a graphics package that was developed by the integrated
11  * circuits group of the Electronics Research Laboratory and the
12  * Department of Electrical Engineering and Computer Sciences at
13  * the University of California, Berkeley, California. The programs
14  * in MFB are available free of charge to any interested party.
15  * The sale, resale, or use of these program for profit without the
16  * express written consent of the Department of Electrical Engineering
17  * and Computer Sciences, University of California, Berkeley, California,
18  * is forbidden.
19  */
20 
21 
22 #include "spice.h"
23 #include "mfb.h"
24 
25 
26 /************************************************************************
27  *
28  * MFBClip
29  *
30  * MFBClip contains routines for special viewport management
31  * and geometry clipping.
32  *
33  * MFBPolygonClip
34  * MFBLineClip
35  * MFBClipArc
36  * MFB_X_Intercept
37  * MFB_Y_Intercept
38  *
39  ************************************************************************/
40 
41 #define CODELEFT 1
42 #define CODEBOTTOM 2
43 #define CODERIGHT 4
44 #define CODETOP 8
45 #define CODE(x,y,c) c = 0;\
46  if(x < l)\
47  c = CODELEFT;\
48  else if(x > r)\
49  c = CODERIGHT;\
50  if(y < b)\
51  c |= CODEBOTTOM;\
52  else if(y > t)\
53  c |= CODETOP;
54 
55 void
56 MFB_Y_Intercept(x1,y1,x2,y2,e,yi)
57 int x1,y1,x2,y2; /* two points on line */
58 int e; /* vertical line of intercept */
59 int *yi; /* y coordinate of intercept */
60 {
61  /*
62  * MFB_Y_Intercept will return the value 'yi' where the the coordinate
63  * (e,yi) is the intersection of the vertical line x = e and the line
64  * determined by the coordinates (x1,y1) and (x2,y2).
65  */
66  *yi = y1;
67  if(x1 == x2) return; /* vertical line */
68  *yi = y1 + ((e - x1) * (y2 - y1))/(x2 - x1);
69 }
70 
71 
72 void
73 MFB_X_Intercept(x1,y1,x2,y2,e,xi)
74 int x1,y1,x2,y2; /* two points on line */
75 int e; /* horizontal line of intercept */
76 int *xi; /* x coordinate of intercept */
77 {
78  /*
79  * MFB_X_Intercept will return the value 'xi' where the the coordinate
80  * (xi,e) is the intersection of the horizontal line y = e and the line
81  * determined by the coordinates (x1,y1) and (x2,y2).
82  */
83  *xi = x1;
84  if(y1 == y2) return; /* horizontal line */
85  *xi = x1 + ((e - y1) * (x2 - x1))/(y2 - y1);
86 }
87 
88 
89 Bool
90 MFBLineClip(pX1,pY1,pX2,pY2,l,b,r,t)
91 int *pX1,*pY1,*pX2,*pY2,l,b,r,t;
92 {
93  /*
94  * MFBLineClip will clip a line to a rectangular area. The returned
95  * value is 'true' if the line is out of the AOI (therefore does not
96  * need to be displayed) and 'false' if the line is in the AOI.
97  */
98  int x1 = *pX1;
99  int y1 = *pY1;
100  int x2 = *pX2;
101  int y2 = *pY2;
102  int x,y,c,c1,c2;
103 
104  CODE(x1,y1,c1)
105  CODE(x2,y2,c2)
106  while(c1 != 0 || c2 != 0) {
107  if((c1 & c2) != 0) return(true); /*Assert: Line is invisible.*/
108  if((c = c1) == 0) c = c2;
109  if(c & CODELEFT) {
110  y = y1+(y2-y1)*(l-x1)/(x2-x1);
111  x = l;
112  }
113  else if(c & CODERIGHT) {
114  y = y1+(y2-y1)*(r-x1)/(x2-x1);
115  x = r;
116  }
117  else if(c & CODEBOTTOM) {
118  x = x1+(x2-x1)*(b-y1)/(y2-y1);
119  y = b;
120  }
121  else if(c & CODETOP) {
122  x = x1+(x2-x1)*(t-y1)/(y2-y1);
123  y = t;
124  }
125  if(c == c1) {
126  x1 = x; y1 = y; CODE(x,y,c1)
127  }
128  else {
129  x2 = x; y2 = y; CODE(x,y,c2)
130  }
131  }
132  *pX1 = x1; *pY1 = y1;
133  *pX2 = x2; *pY2 = y2;
134  return(false); /*Assert: Line is at least partially visible.*/
135 }
136 
137 
138 void
139 MFBPolygonClip(poly,left,bottom,right,top)
140 MFBPOLYGON *poly;
141 int top,bottom,left,right; /* bounding box */
142 {
143  /*
144  * MFBPolygonClip will take the polygon 'poly' and clip it to the
145  * box described by 'top','bottom','left', and 'right'.
146  */
147  MFBPOLYGON p1,p2;
148  static int polybuffer1[MFBPOLYGONBUFSIZE];
149  static int polybuffer2[MFBPOLYGONBUFSIZE];
150  int i,k,n,*swap;
151  int minx, miny, maxx, maxy;
152 
153  if(top < bottom)
154  MFBSwapInt(top,bottom);
155  if(right < left)
156  MFBSwapInt(left,right);
157 
158  n = poly->nvertices << 1; /* fast multiplication by 2 */
159  if(n < 4) return;
160  n = MFBmin(MFBPOLYGONBUFSIZE,n);
161  p1.xy = polybuffer1;
162  p2.xy = polybuffer2;
163  minx = maxx = poly->xy[0];
164  miny = maxy = poly->xy[1];
165  for(i=0; i<n; i++){
166  p2.xy[i] = poly->xy[i];
167  maxx = MFBmax(p2.xy[i],maxx);
168  minx = MFBmin(p2.xy[i],minx);
169  ++i;
170  p2.xy[i] = poly->xy[i];
171  maxy = MFBmax(p2.xy[i],maxy);
172  miny = MFBmin(p2.xy[i],miny);
173  }
174 
175  /* test if clipping is necessary */
176  poly->nvertices = 0;
177  if(maxx < left || minx > right || maxy < bottom || miny > top)
178  return;
179 
180  /*
181  * start with the right side first
182  */
183  k = i = 0;
184  while(p2.xy[i] > right && i < n) i += 2;
185  if(i == 0){
186  p1.xy[k++] = p2.xy[i++];
187  p1.xy[k++] = p2.xy[i++];
188  }
189  else if(i == n)
190  return;
191  else {
192  p1.xy[k++] = right;
193  MFB_Y_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
194  right,&p1.xy[k++]);
195  }
196  while(i < n){
197  if(p2.xy[i] <= right){
198  p1.xy[k++] = p2.xy[i++];
199  p1.xy[k++] = p2.xy[i++];
200  }
201  else {
202  if(p2.xy[i-2] != right){
203  p1.xy[k++] = right;
204  MFB_Y_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
205  right,&p1.xy[k++]);
206  }
207  while(i < n && p2.xy[i] > right) i += 2;
208  if(i < n && p2.xy[i] <= right){
209  p1.xy[k++] = right;
210  MFB_Y_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
211  right,&p1.xy[k++]);
212  }
213  }
214  }
215  if((p2.xy[0] > right && p2.xy[n-2] <= right) ||
216  (p2.xy[0] <= right && p2.xy[n-2] > right)){
217  p1.xy[k++] = right;
218  MFB_Y_Intercept(p2.xy[0],p2.xy[1],p2.xy[n-2],p2.xy[n-1],right,
219  &p1.xy[k++]);
220  }
221  if(k < 4) return;
222  n = MFBmin(MFBPOLYGONBUFSIZE,k);
223  swap = p1.xy;
224  p1.xy = p2.xy;
225  p2.xy = swap;
226 
227  /*
228  * next the left side
229  */
230  k = i = 0;
231  while(p2.xy[i] < left && i < n) i += 2;
232  if(i == 0){
233  p1.xy[k++] = p2.xy[i++];
234  p1.xy[k++] = p2.xy[i++];
235  }
236  else if(i == n)
237  return;
238  else {
239  p1.xy[k++] = left;
240  MFB_Y_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],left,
241  &p1.xy[k++]);
242  }
243  while(i < n){
244  if(p2.xy[i] >= left){
245  p1.xy[k++] = p2.xy[i++];
246  p1.xy[k++] = p2.xy[i++];
247  }
248  else {
249  if(p2.xy[i-2] != left){
250  p1.xy[k++] = left;
251  MFB_Y_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
252  left,&p1.xy[k++]);
253  }
254  while(i < n && p2.xy[i] < left) i += 2;
255  if(i < n && p2.xy[i] >= left){
256  p1.xy[k++] = left;
257  MFB_Y_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
258  left,&p1.xy[k++]);
259  }
260  }
261  }
262  if((p2.xy[0] < left && p2.xy[n-2] >= left) ||
263  (p2.xy[0] >= left && p2.xy[n-2] < left)){
264  p1.xy[k++] = left;
265  MFB_Y_Intercept(p2.xy[0],p2.xy[1],p2.xy[n-2],p2.xy[n-1],left,
266  &p1.xy[k++]);
267  }
268  if(k < 4) return;
269  n = MFBmin(MFBPOLYGONBUFSIZE,k);
270  swap = p1.xy;
271  p1.xy = p2.xy;
272  p2.xy = swap;
273 
274  /*
275  * next the top side
276  */
277  k = i = 0;
278  while(p2.xy[i+1] > top && i < n) i += 2;
279  if(i == 0){
280  p1.xy[k++] = p2.xy[i++];
281  p1.xy[k++] = p2.xy[i++];
282  }
283  else if(i == n)
284  return;
285  else {
286  MFB_X_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],top,
287  &p1.xy[k++]);
288  p1.xy[k++] = top;
289  }
290  while(i < n){
291  if(p2.xy[i+1] <= top){
292  p1.xy[k++] = p2.xy[i++];
293  p1.xy[k++] = p2.xy[i++];
294  }
295  else {
296  if(p2.xy[i-1] != top){
297  MFB_X_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
298  top,&p1.xy[k++]);
299  p1.xy[k++] = top;
300  }
301  while(i < n && p2.xy[i+1] > top) i += 2;
302  if(i < n && p2.xy[i+1] <= top){
303  MFB_X_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
304  top,&p1.xy[k++]);
305  p1.xy[k++] = top;
306  }
307  }
308  }
309  if((p2.xy[1] > top && p2.xy[n-1] <= top) ||
310  (p2.xy[1] <= top && p2.xy[n-1] > top)){
311  MFB_X_Intercept(p2.xy[0],p2.xy[1],p2.xy[n-2],p2.xy[n-1],top,
312  &p1.xy[k++]);
313  p1.xy[k++] = top;
314  }
315  if(k < 4) return;
316  n = MFBmin(MFBPOLYGONBUFSIZE,k);
317  swap = p1.xy;
318  p1.xy = p2.xy;
319  p2.xy = swap;
320 
321  /*
322  * finally the bottom side
323  */
324  i = k = 0;
325  while(p2.xy[i+1] < bottom && i < n) i += 2;
326  if(i == 0){
327  p1.xy[k++] = p2.xy[i++];
328  p1.xy[k++] = p2.xy[i++];
329  }
330  else if(i == n)
331  return;
332  else {
333  MFB_X_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],bottom,
334  &p1.xy[k++]);
335  p1.xy[k++] = bottom;
336  }
337  while(i < n){
338  if(p2.xy[i+1] >= bottom){
339  p1.xy[k++] = p2.xy[i++];
340  p1.xy[k++] = p2.xy[i++];
341  }
342  else {
343  if(p2.xy[i-1] != bottom){
344  MFB_X_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
345  bottom,&p1.xy[k++]);
346  p1.xy[k++] = bottom;
347  }
348  while(i < n && p2.xy[i+1] < bottom) i += 2;
349  if(i < n && p2.xy[i+1] >= bottom){
350  MFB_X_Intercept(p2.xy[i-2],p2.xy[i-1],p2.xy[i],p2.xy[i+1],
351  bottom,&p1.xy[k++]);
352  p1.xy[k++] = bottom;
353  }
354  }
355  }
356  if((p2.xy[1] < bottom && p2.xy[n-1] >= bottom) ||
357  (p2.xy[1] >= bottom && p2.xy[n-1] < bottom)){
358  MFB_X_Intercept(p2.xy[0],p2.xy[1],p2.xy[n-2],p2.xy[n-1],bottom,
359  &p1.xy[k++]);
360  p1.xy[k++] = bottom;
361  }
362  if(k < 4) return;
363  k = MFBmin(MFBPOLYGONBUFSIZE,k);
364  poly->nvertices = k >> 1;
365 
366  /*
367  * Transfer coordinates to poly buffer and one last clipping
368  */
369  for(i=0; i<k; i += 2){
370  poly->xy[i] = MFBmax(MFBmin(p1.xy[i],right),left);
371  poly->xy[i+1] = MFBmax(MFBmin(p1.xy[i+1],top),bottom);
372  }
373 }
374 
375 
376 
377 MFBPATH
378 *MFBClipArc(path,left,bottom,right,top)
379 MFBPATH *path;
380 int left,bottom,right,top;
381  /*
382  * Notes:
383  */
384 {
385  int n,x1,y1,x2,y2,lastX,lastY,newX,newY,pathnum=0;
386  static MFBPATH pbuf[5];
387  static int xy[5 * MFBPOLYGONBUFSIZE];
388 
389  /* allocate buffer */
390  for(n=0; n<5; ++n){
391  pbuf[n].xy = &xy[n * MFBPOLYGONBUFSIZE];
392  pbuf[n].nvertices = 0;
393  }
394 
395  if(right < left)
396  MFBSwapInt(right,left);
397  if(top < bottom)
398  MFBSwapInt(top,bottom);
399 
400  n = 0;
401  while(n < path->nvertices){
402  newX = path->xy[n + n];
403  newY = path->xy[n + n + 1];
404  n++;
405  /* find first point (newX,newY) which is in AOI */
406  if(left <= newX && right >= newX && bottom <= newY && top >= newY)
407  break;
408  lastX = newX;
409  lastY = newY;
410  }
411 
412  if(n > 1){
413  x1 = lastX;
414  y1 = lastY;
415  x2 = newX;
416  y2 = newY;
417  if(MFBLineClip(&x1,&y1,&x2,&y2,left,bottom,right,top))
418  /* not even close to being in AOI */
419  return(pbuf);
420  pbuf[pathnum].xy[0] = x1;
421  pbuf[pathnum].xy[1] = y1;
422  pbuf[pathnum].xy[2] = x2;
423  pbuf[pathnum].xy[3] = y2;
424  pbuf[pathnum].nvertices = 4;
425  }
426  else{
427  pbuf[pathnum].xy[0] = newX;
428  pbuf[pathnum].xy[1] = newY;
429  pbuf[pathnum].nvertices = 2;
430  }
431  while(n < path->nvertices && pathnum < 5){
432  x1 = lastX = newX; y1 = lastY = newY;
433  x2 = newX = path->xy[n + n]; y2 = newY = path->xy[n + n + 1];
434  n++;
435  MFBLineClip(&x1,&y1,&x2,&y2,left,bottom,right,top);
436  /* are we in the AOI? */
437  if(left < lastX && right > lastX && bottom < lastY && top > lastY){
438  pbuf[pathnum].xy[pbuf[pathnum].nvertices++] = x2;
439  pbuf[pathnum].xy[pbuf[pathnum].nvertices++] = y2;
440  }
441  /* or are we entering the AOI? */
442  else if(left < newX && right > newX && bottom < newY && top > newY){
443  if(++pathnum < 5){
444  pbuf[pathnum].xy[0] = x1; pbuf[pathnum].xy[1] = y1;
445  pbuf[pathnum].xy[2] = x2; pbuf[pathnum].xy[3] = y2;
446  pbuf[pathnum].nvertices=4;
447  }
448  }
449  }
450  for(n=0; n<5; ++n)
451  pbuf[n].nvertices /= 2;
452  return(pbuf);
453 }
454 
#define CODETOP
Definition: mfbclip.c:44
int nvertices
Definition: mfb.h:105
MFBPATH * MFBClipArc(MFBPATH *path, int left, int bottom, int right, int top)
Definition: mfbclip.c:378
static double e
Definition: vectors.c:17
Definition: cddefs.h:312
#define MFBPOLYGONBUFSIZE
Definition: mfb.h:31
#define CODELEFT
Definition: mfbclip.c:41
Bool
Definition: mfb.h:18
#define MFBmin(a, b)
Definition: mfb.h:34
#define CODERIGHT
Definition: mfbclip.c:43
Definition: mfb.h:104
static double c
Definition: vectors.c:16
Bool MFBLineClip(int *pX1, int *pY1, int *pX2, int *pY2, int l, int b, int r, int t)
Definition: mfbclip.c:90
void MFB_X_Intercept(int x1, int y1, int x2, int y2, int e, int *xi)
Definition: mfbclip.c:73
#define swap(a, b)
Definition: hplaser.c:34
#define MFBmax(a, b)
Definition: mfb.h:33
Definition: cddefs.h:162
#define CODE(x, y, c)
Definition: mfbclip.c:45
#define MFBSwapInt(f1, f2)
Definition: mfb.h:35
void MFBPolygonClip(MFBPOLYGON *poly, int left, int bottom, int right, int top)
Definition: mfbclip.c:139
void MFB_Y_Intercept(int x1, int y1, int x2, int y2, int e, int *yi)
Definition: mfbclip.c:56
static char * path
Definition: paths.c:13
Definition: cddefs.h:192
#define CODEBOTTOM
Definition: mfbclip.c:42
int * xy
Definition: mfb.h:106