BRL-CAD
nurb_flat.c
Go to the documentation of this file.
1 /* N U R B _ F L A T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1990-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 /** @addtogroup nurb */
21 /** @{ */
22 /** @file primitives/bspline/nurb_flat.c
23  *
24  * Tests the NURB surface to see if its flat depending on the epsilon
25  * passed.
26  *
27  */
28 /** @} */
29 
30 #include "common.h"
31 
32 #include <math.h>
33 #include "bio.h"
34 
35 #include "vmath.h"
36 #include "raytrace.h"
37 #include "nurb.h"
38 
39 /* This doesn't seem to be used anymore: */
40 /* extern fastf_t spl_crv_flat(); */
41 
42 
43 int
44 rt_nurb_s_flat(struct face_g_snurb *srf, fastf_t epsilon)
45 
46  /* Epsilon value for flatness testing */
47 {
48  register fastf_t max_row_dist;
49  register fastf_t max_col_dist;
50  register fastf_t max_dist;
51  int dir;
52  fastf_t * mesh_ptr = srf->ctl_points;
53  int coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
54  int j, i, k;
55  int mesh_elt;
56  vect_t p1, p2, p3, p4, v1, v2, v3;
57  vect_t nrm;
58  fastf_t nrmln;
59  fastf_t dist;
60  fastf_t * crv;
61  int otherdir;
62 
63  dir = srf->dir;
64 
65  otherdir = (dir == RT_NURB_SPLIT_ROW) ? RT_NURB_SPLIT_COL : RT_NURB_SPLIT_ROW;
66 
67  max_row_dist = max_col_dist = -INFINITY;
68 
69  crv = (fastf_t *) bu_malloc(sizeof(fastf_t) *
70  RT_NURB_EXTRACT_COORDS(srf->pt_type) * srf->s_size[1],
71  "rt_nurb_s_flat: crv");
72 
73  /* Test Row and RT_NURB_SPLIT_COL curves for flatness, If a curve
74  * is not flat than get distance to line
75  */
76 
77  /* Test Row Curves */
78 
79  for (i = 0; i < (srf->s_size[0]); i++) {
80  fastf_t rdist;
81  for (j = 0;
82  j < (srf->s_size[1] *
83  RT_NURB_EXTRACT_COORDS(srf->pt_type));
84  j++)
85  crv[j] = *mesh_ptr++;
86 
87  rdist = rt_nurb_crv_flat(crv, srf->s_size[1],
88  srf->pt_type);
89  max_row_dist = FMAX(max_row_dist, rdist);
90  }
91 
92  bu_free((char *)crv, "rt_nurb_s_flat: crv");
93 
94  crv = (fastf_t *) bu_malloc(sizeof(fastf_t) *
95  RT_NURB_EXTRACT_COORDS(srf->pt_type) *
96  srf->s_size[0], "rt_nurb_s_flat: crv");
97 
98  for (i = 0; i < (coords * srf->s_size[1]); i += coords) {
99  fastf_t rdist;
100 
101  for (j = 0; j < (srf->s_size[0]); j++) {
102  mesh_elt =
103  (j * (srf->s_size[1] * coords)) + i;
104 
105  for (k = 0; k < coords; k++)
106  crv[j * coords + k] =
107  srf->ctl_points[mesh_elt + k];
108  }
109 
110  rdist = rt_nurb_crv_flat(crv,
111  srf->s_size[0], srf->pt_type);
112 
113  max_col_dist = FMAX(max_col_dist, rdist);
114  }
115 
116  bu_free((char *)crv, "rt_nurb_s_flat: crv");
117 
118  max_dist = FMAX(max_row_dist, max_col_dist);
119 
120  if (max_dist > epsilon) {
121  if (max_row_dist > max_col_dist)
122  return RT_NURB_SPLIT_ROW;
123  else
124  return RT_NURB_SPLIT_COL;
125  }
126 
127  /* Test the corners to see if they lie in a plane. */
128 
129  /*
130  * Extract the four corners and put a plane through three of them
131  * and see how far the fourth is to the plane.
132  */
133 
134  mesh_ptr = srf->ctl_points;
135 
136  if (!RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
137 
138  VMOVE(p1, mesh_ptr);
139  VMOVE(p2,
140  (mesh_ptr + (srf->s_size[1] - 1) * coords));
141  VMOVE(p3,
142  (mesh_ptr +
143  ((srf->s_size[1] *
144  (srf->s_size[0] - 1)) +
145  (srf->s_size[1] - 1)) * coords));
146 
147  VMOVE(p4,
148  (mesh_ptr +
149  (srf->s_size[1] *
150  (srf->s_size[0] - 1)) * coords));
151  } else {
152  hvect_t h1, h2, h3, h4;
153  int offset;
154 
155  HMOVE(h1, mesh_ptr);
156  HDIVIDE(p1, h1);
157 
158  offset = (srf->s_size[1] - 1) * coords;
159  HMOVE(h2, mesh_ptr + offset);
160  HDIVIDE(p2, h2);
161 
162  offset =
163  ((srf->s_size[1] *
164  (srf->s_size[0] - 1)) +
165  (srf->s_size[1] - 1)) * coords;
166  HMOVE(h3, mesh_ptr + offset);
167  HDIVIDE(p3, h3);
168 
169  offset =
170  (srf->s_size[1] *
171  (srf->s_size[0] - 1)) * coords;
172  HMOVE(h4, mesh_ptr + offset);
173  HDIVIDE(p4, h4);
174  }
175 
176  VSUB2(v1, p2, p1);
177  VSUB2(v2, p3, p1);
178 
179  VCROSS(nrm, v1, v2);
180 
181  nrmln = MAGNITUDE(nrm);
182  if (nrmln < 0.0001) /* XXX Why this constant? */
183  return RT_NURB_SPLIT_FLAT;
184 
185  VSUB2(v3, p4, p1);
186 
187  dist = fabs(VDOT(v3, nrm)) / nrmln;
188 
189  if (dist > epsilon)
190  return otherdir;
191 
192  return RT_NURB_SPLIT_FLAT; /* Must be flat */
193 
194 }
195 
196 
197 fastf_t
198 rt_nurb_crv_flat(fastf_t *crv, int size, int pt_type)
199 {
200  point_t p1, p2;
201  vect_t ln;
202  int i;
203  fastf_t dist;
204  fastf_t max_dist;
205  fastf_t length;
206  fastf_t * c_ptr;
207  vect_t testv, xp;
208  hvect_t h1, h2;
209  int coords;
210  int rational;
211 
212  coords = RT_NURB_EXTRACT_COORDS(pt_type);
213  rational = RT_NURB_IS_PT_RATIONAL(pt_type);
214  max_dist = -INFINITY;
215 
216  if (!rational) {
217  VMOVE(p1, crv);
218  } else {
219  HMOVE(h1, crv);
220  HDIVIDE(p1, h1);
221  }
222 
223  length = 0.0;
224 
225  /*
226  * loop through all of the points until a line is found which may
227  * not be the end pts of the curve if the endpoints are the same.
228  */
229  for (i = size - 1; (i > 0) && length < SQRT_SMALL_FASTF; i--) {
230  if (!rational) {
231  VMOVE(p2, (crv + (i * coords)));
232  } else {
233  HMOVE(h2, (crv + (i * coords)));
234  HDIVIDE(p2, h2);
235  }
236 
237  VSUB2(ln, p1, p2);
238  length = MAGNITUDE(ln);
239  }
240 
241 
242  if (length >= SQRT_SMALL_FASTF) {
243  VSCALE(ln, ln, 1.0 / length);
244  c_ptr = crv + coords;
245 
246  for (i = 1; i < size; i++) {
247  if (!rational) {
248  VSUB2(testv, p1, c_ptr);
249  } else {
250  HDIVIDE(h2, c_ptr);
251  VSUB2(testv, p1, h2);
252  }
253 
254  VCROSS(xp, testv, ln);
255  dist = MAGNITUDE(xp);
256  max_dist = FMAX(max_dist, dist);
257  c_ptr += coords;
258  }
259  }
260  return max_dist;
261 }
262 
263 
264 /*
265  * Local Variables:
266  * mode: C
267  * tab-width: 8
268  * indent-tabs-mode: t
269  * c-file-style: "stroustrup"
270  * End:
271  * ex: shiftwidth=4 tabstop=8
272  */
int rt_nurb_s_flat(struct face_g_snurb *srf, fastf_t epsilon)
Definition: nurb_flat.c:44
Header file for the BRL-CAD common definitions.
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
fastf_t rt_nurb_crv_flat(fastf_t *crv, int size, int pt_type)
Definition: nurb_flat.c:198
#define SQRT_SMALL_FASTF
Definition: defines.h:346
#define FMAX(a, b)
Definition: common.h:102
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
double fastf_t
Definition: defines.h:300