BRL-CAD
clip.c
Go to the documentation of this file.
1 /* C L I P . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1985-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libdm/clip.c
21  *
22  * Authors - clip() was started on 14 October 81, Based on the
23  * clipping routine in "Principles of Computer Graphics" by Newman and
24  * Sproull, 1973, McGraw/Hill.
25  *
26  */
27 
28 #include "common.h"
29 
30 
31 #include "vmath.h"
32 #include "dm.h"
33 
34 /* XXX need to test more thoroughly
35  #define ANGLE_EPSILON 0.0001
36  #define CLIP_DISTANCE 1000000000.0
37 */
38 #define EPSILON 0.0001
39 #define CLIP_DISTANCE 100000000.0
40 
41 
42 HIDDEN int
44 {
45  int cval;
46 
47  cval = 0;
48  if (x < GED_MIN)
49  cval |= 01;
50  else if (x > GED_MAX)
51  cval |= 02;
52 
53  if (y < GED_MIN)
54  cval |= 04;
55  else if (y > GED_MAX)
56  cval |= 010;
57 
58  return cval;
59 }
60 
61 
62 /**
63  * clip a 2-D integer line seg against the size of the display
64  */
65 int
66 clip(fastf_t *xp1, fastf_t *yp1, fastf_t *xp2, fastf_t *yp2)
67 {
68  char code1, code2;
69 
70  code1 = code(*xp1, *yp1);
71  code2 = code(*xp2, *yp2);
72 
73  while (code1 || code2) {
74  if (code1 & code2)
75  return -1; /* No part is visible */
76 
77  /* SWAP codes, X's, and Y's */
78  if (code1 == 0) {
79  char ctemp;
80  fastf_t temp;
81 
82  ctemp = code1;
83  code1 = code2;
84  code2 = ctemp;
85 
86  temp = *xp1;
87  *xp1 = *xp2;
88  *xp2 = temp;
89 
90  temp = *yp1;
91  *yp1 = *yp2;
92  *yp2 = temp;
93  }
94 
95  if (code1 & 01) {
96  /* Push toward left edge */
97  *yp1 = *yp1 + (*yp2-*yp1)*(GED_MIN-*xp1)/(*xp2-*xp1);
98  *xp1 = GED_MIN;
99  } else if (code1 & 02) {
100  /* Push toward right edge */
101  *yp1 = *yp1 + (*yp2-*yp1)*(GED_MAX-*xp1)/(*xp2-*xp1);
102  *xp1 = GED_MAX;
103  } else if (code1 & 04) {
104  /* Push toward bottom edge */
105  *xp1 = *xp1 + (*xp2-*xp1)*(GED_MIN-*yp1)/(*yp2-*yp1);
106  *yp1 = GED_MIN;
107  } else if (code1 & 010) {
108  /* Push toward top edge */
109  *xp1 = *xp1 + (*xp2-*xp1)*(GED_MAX-*yp1)/(*yp2-*yp1);
110  *yp1 = GED_MAX;
111  }
112 
113  code1 = code(*xp1, *yp1);
114  }
115 
116  return 0;
117 }
118 
119 
120 /**
121  * Clip a ray against a rectangular parallelepiped (RPP) that has faces
122  * parallel to the coordinate planes (a clipping RPP). The RPP is
123  * defined by a minimum point and a maximum point.
124  *
125  * Returns -
126  * 0 if ray does not hit RPP,
127  * !0 if ray hits RPP.
128  *
129  * Implicit Return -
130  * if !0 was returned, "a" and "b" have been clipped to the RPP.
131  */
132 int
133 vclip(vect_t a, vect_t b, fastf_t *min, fastf_t *max)
134 {
135  static vect_t diff;
136  static double sv;
137  static double st;
138  static double mindist, maxdist;
139  fastf_t *pt = &a[0];
140  fastf_t *dir = &diff[0];
141  int i;
142 
143  mindist = -CLIP_DISTANCE;
144  maxdist = CLIP_DISTANCE;
145  VSUB2(diff, b, a);
146 
147  for (i=0; i < 3; i++, pt++, dir++, max++, min++) {
148  if (*dir < -EPSILON) {
149  if ((sv = (*min - *pt) / *dir) < 0.0)
150  return 0; /* MISS */
151  if (maxdist > sv)
152  maxdist = sv;
153  if (mindist < (st = (*max - *pt) / *dir))
154  mindist = st;
155  } else if (*dir > EPSILON) {
156  if ((st = (*max - *pt) / *dir) < 0.0)
157  return 0; /* MISS */
158  if (maxdist > st)
159  maxdist = st;
160  if (mindist < ((sv = (*min - *pt) / *dir)))
161  mindist = sv;
162  } else {
163  /*
164  * If direction component along this axis is NEAR 0,
165  * (i.e., this ray is aligned with this axis), merely
166  * check against the boundaries.
167  */
168  if ((*min > *pt) || (*max < *pt))
169  return 0; /* MISS */;
170  }
171  }
172  if (mindist >= maxdist)
173  return 0; /* MISS */
174 
175  if (mindist > 1 || maxdist < 0)
176  return 0; /* MISS */
177 
178  if (mindist <= 0 && maxdist >= 1)
179  return 1; /* HIT, no clipping needed */
180 
181  /* Don't grow one end of a contained segment */
182  if (mindist < 0)
183  mindist = 0;
184  if (maxdist > 1)
185  maxdist = 1;
186 
187  /* Compute actual intercept points */
188  VJOIN1(b, a, maxdist, diff); /* b must go first */
189  VJOIN1(a, a, mindist, diff);
190  return 1; /* HIT */
191 }
192 
193 
194 /*
195  * Local Variables:
196  * mode: C
197  * tab-width: 8
198  * indent-tabs-mode: t
199  * c-file-style: "stroustrup"
200  * End:
201  * ex: shiftwidth=4 tabstop=8
202  */
#define GED_MAX
Definition: ged.h:253
#define st
Header file for the BRL-CAD common definitions.
#define HIDDEN
Definition: common.h:86
#define GED_MIN
Definition: ged.h:254
HIDDEN int code(fastf_t x, fastf_t y)
Definition: clip.c:43
int vclip(vect_t a, vect_t b, fastf_t *min, fastf_t *max)
Definition: clip.c:133
int clip(fastf_t *xp1, fastf_t *yp1, fastf_t *xp2, fastf_t *yp2)
Definition: clip.c:66
#define CLIP_DISTANCE
Definition: clip.c:39
#define EPSILON
Definition: clip.c:38
basis_s * b
Definition: chull3d.cpp:151
double fastf_t
Definition: defines.h:300