Jspice3
clip.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1982 Giles Billingsley
5  1986 Wayne A. Christopher
6  1993 Stephen R. Whiteley
7 ****************************************************************************/
8 
9 /*
10  * Some routines to do clipping of polygons, etc to boxes. Most of this code
11  * was rescued from MFB:
12  */
13 
14 #include "spice.h"
15 #include "plotdefs.h"
16 
17 #define CODEMINX 1
18 #define CODEMINY 2
19 #define CODEMAXX 4
20 #define CODEMAXY 8
21 #define CODE(x,y,c) c = 0;\
22  if (x < l)\
23  c = CODEMINX;\
24  else if (x > r)\
25  c = CODEMAXX;\
26  if (y < b)\
27  c |= CODEMINY;\
28  else if (y > t)\
29  c |= CODEMAXY;
30 
31 /* XXX */
32 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
33 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
34 #define SWAM_PINT(a, b) { int xxxx = (a); (a) = (b); (b) = xxxx; }
35 
36 /* clip_line will clip a line to a rectangular area. The returned
37  * value is 'true' if the line is out of the AOI (therefore does not
38  * need to be displayed) and 'false' if the line is in the AOI.
39  */
40 
41 bool
42 clip_line(pX1,pY1,pX2,pY2,l,b,r,t)
43  int *pX1, *pY1, *pX2, *pY2, l, b, r, t;
44 {
45  int x1 = *pX1;
46  int y1 = *pY1;
47  int x2 = *pX2;
48  int y2 = *pY2;
49  int x,y,c,c1,c2;
50 
51  CODE(x1,y1,c1)
52  CODE(x2,y2,c2)
53  while (c1 || c2) {
54  if (c1 & c2)
55  return (true); /* Line is invisible. */
56  if (!(c = c1))
57  c = c2;
58  if (c & CODEMINX) {
59  y = y1+(y2-y1)*(l-x1)/(x2-x1);
60  x = l;
61  } else if (c & CODEMAXX) {
62  y = y1+(y2-y1)*(r-x1)/(x2-x1);
63  x = r;
64  } else if (c & CODEMINY) {
65  x = x1+(x2-x1)*(b-y1)/(y2-y1);
66  y = b;
67  } else if (c & CODEMAXY) {
68  x = x1+(x2-x1)*(t-y1)/(y2-y1);
69  y = t;
70  }
71  if (c == c1) {
72  x1 = x;
73  y1 = y;
74  CODE(x,y,c1)
75  } else {
76  x2 = x;
77  y2 = y;
78  CODE(x,y,c2)
79  }
80  }
81  *pX1 = x1;
82  *pY1 = y1;
83  *pX2 = x2;
84  *pY2 = y2;
85  return (false); /* Line is at least partially visible.*/
86 }
87 
88 /* This routine will clip a line to a circle, returning true if the line
89  * is entirely outside the circle. Note that we have to be careful not
90  * to switch the points around, since in grid.c we need to know which is
91  * the outer point for putting the label on.
92  */
93 
94 bool
95 clip_to_circle(x1, y1, x2, y2, cx, cy, rad)
96  int *x1, *y1, *x2, *y2, cx, cy, rad;
97 {
98  double perplen, a, b, c;
99  double tx, ty, dt;
100  double dtheta;
101  double theta1, theta2, tt, alpha, beta, gamma;
102  bool flip = false;
103  int i;
104 
105  /* Get the angles between the origin and the endpoints. */
106  if ((*x1-cx) || (*y1-cy))
107  theta1 = atan2((double) *y1 - cy, (double) *x1 - cx);
108  else
109  theta1 = M_PI;
110  if ((*x2-cx) || (*y2-cy))
111  theta2 = atan2((double) *y2 - cy, (double) *x2 - cx);
112  else
113  theta2 = M_PI;
114 
115  if (theta1 < 0.0)
116  theta1 = 2 * M_PI + theta1;
117  if (theta2 < 0.0)
118  theta2 = 2 * M_PI + theta2;
119 
120  dtheta = theta2 - theta1;
121  if (dtheta > M_PI)
122  dtheta = dtheta - 2 * M_PI;
123  else if (dtheta < - M_PI)
124  dtheta = 2 * M_PI - dtheta;
125 
126  /* Make sure that p1 is the first point */
127  if (dtheta < 0) {
128  tt = theta1;
129  theta1 = theta2;
130  theta2 = tt;
131  i = *x1;
132  *x1 = *x2;
133  *x2 = i;
134  i = *y1;
135  *y1 = *y2;
136  *y2 = i;
137  flip = true;
138  dtheta = -dtheta;
139  }
140 
141  /* Figure out the distances between the points */
142  a = sqrt((double) ((*x1 - cx) * (*x1 - cx) + (*y1 - cy) * (*y1 - cy)));
143  b = sqrt((double) ((*x2 - cx) * (*x2 - cx) + (*y2 - cy) * (*y2 - cy)));
144  c = sqrt((double) ((*x1 - *x2) * (*x1 - *x2) +
145  (*y1 - *y2) * (*y1 - *y2)));
146 
147  /* We have three cases now -- either the midpoint of the line is
148  * closest to the origon, or point 1 or point 2 is. Actually the
149  * midpoint won't in general be the closest, but if a point besides
150  * one of the endpoints is closest, the midpoint will be closer than
151  * both endpoints.
152  */
153  tx = (*x1 + *x2) / 2;
154  ty = (*y1 + *y2) / 2;
155  dt = sqrt((double) ((tx - cx) * (tx - cx) + (ty - cy) * (ty - cy)));
156  if ((dt < a) && (dt < b)) {
157  /* This is wierd -- round-off errors I guess. */
158  tt = (a * a + c * c - b * b) / (2 * a * c);
159  if (tt > 1.0)
160  tt = 1.0;
161  else if (tt < -1.0)
162  tt = -1.0;
163  alpha = acos(tt);
164  perplen = a * sin(alpha);
165  } else if (a < b) {
166  perplen = a;
167  } else {
168  perplen = b;
169  }
170 
171  /* Now we should see if the line is outside of the circle */
172  if (perplen >= rad)
173  return (true);
174 
175  /* It's at least partially inside */
176  if (a > rad) {
177  tt = (a * a + c * c - b * b) / (2 * a * c);
178  if (tt > 1.0)
179  tt = 1.0;
180  else if (tt < -1.0)
181  tt = -1.0;
182  alpha = acos(tt);
183  gamma = asin(sin(alpha) * a / rad);
184  if (gamma < M_PI / 2)
185  gamma = M_PI - gamma;
186  beta = M_PI - alpha - gamma;
187  *x1 = cx + rad * cos(theta1 + beta);
188  *y1 = cy + rad * sin(theta1 + beta);
189  }
190  if (b > rad) {
191  tt = (c * c + b * b - a * a) / (2 * b * c);
192  if (tt > 1.0)
193  tt = 1.0;
194  else if (tt < -1.0)
195  tt = -1.0;
196  alpha = acos(tt);
197  gamma = asin(sin(alpha) * b / rad);
198  if (gamma < M_PI / 2)
199  gamma = M_PI - gamma;
200  beta = M_PI - alpha - gamma;
201  *x2 = cx + rad * cos(theta2 - beta);
202  *y2 = cy + rad * sin(theta2 - beta);
203  }
204  if (flip) {
205  i = *x1;
206  *x1 = *x2;
207  *x2 = i;
208  i = *y1;
209  *y1 = *y2;
210  *y2 = i;
211  }
212  return (false);
213 }
#define CODEMINY
Definition: clip.c:18
Definition: xforms.c:16
#define M_PI
Definition: spice.h:132
#define CODEMAXX
Definition: clip.c:19
#define CODEMAXY
Definition: clip.c:20
Definition: cddefs.h:312
#define CODE(x, y, c)
Definition: clip.c:21
bool clip_line(int *pX1, int *pY1, int *pX2, int *pY2, int l, int b, int r, int t)
Definition: clip.c:42
Definition: sced.h:120
double cos()
static double c
Definition: vectors.c:16
double sin()
Definition: cddefs.h:162
#define CODEMINX
Definition: clip.c:17
Definition: cddefs.h:192
bool clip_to_circle(int *x1, int *y1, int *x2, int *y2, int cx, int cy, int rad)
Definition: clip.c:95