BRL-CAD
vol.c
Go to the documentation of this file.
1 /* V O L . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1989-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 primitives */
21 /** @{ */
22 /** @file primitives/vol/vol.c
23  *
24  * Intersect a ray with a 3-D volume. The volume is described as a
25  * concatenation of bw(5) files.
26  *
27  */
28 /** @} */
29 
30 #include "common.h"
31 
32 #include <stddef.h>
33 #include <ctype.h>
34 #include <math.h>
35 #include <string.h>
36 #include "bio.h"
37 
38 #include "bu/parallel.h"
39 #include "vmath.h"
40 #include "db.h"
41 #include "nmg.h"
42 #include "rtgeom.h"
43 #include "raytrace.h"
44 
45 #include "../fixpt.h"
46 
47 
48 /*
49  NOTES:
50  Changed small to small1 for win32 compatibility
51 */
52 
53 
55  struct rt_vol_internal vol_i;
56  vect_t vol_xnorm; /* local +X norm in model coords */
57  vect_t vol_ynorm;
58  vect_t vol_znorm;
59  mat_t vol_mat; /* model to ideal space */
60  vect_t vol_origin; /* local coords of grid origin (0, 0, 0) for now */
61  vect_t vol_large; /* local coords of XYZ max */
62 };
63 #define VOL_NULL ((struct rt_vol_specific *)0)
64 
65 #define VOL_O(m) bu_offsetof(struct rt_vol_internal, m)
66 
67 const struct bu_structparse rt_vol_parse[] = {
68  {"%s", RT_VOL_NAME_LEN, "file", bu_offsetof(struct rt_vol_internal, file), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
69  {"%d", 1, "w", VOL_O(xdim), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
70  {"%d", 1, "n", VOL_O(ydim), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
71  {"%d", 1, "d", VOL_O(zdim), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
72  {"%d", 1, "lo", VOL_O(lo), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
73  {"%d", 1, "hi", VOL_O(hi), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
74  {"%f", ELEMENTS_PER_VECT, "size", bu_offsetof(struct rt_vol_internal, cellsize), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
75  {"%f", 16, "mat", bu_offsetof(struct rt_vol_internal, mat), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
76  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
77 };
78 
79 
80 extern void rt_vol_plate(point_t a, point_t b, point_t c, point_t d,
81  mat_t mat, struct bu_list *vhead, struct rt_vol_internal *vip);
82 
83 /*
84  * Codes to represent surface normals.
85  * In a bitmap, there are only 4 possible normals.
86  * With this code, reverse the sign to reverse the direction.
87  * As always, the normal is expected to point outwards.
88  */
89 #define NORM_ZPOS 3
90 #define NORM_YPOS 2
91 #define NORM_XPOS 1
92 #define NORM_XNEG (-1)
93 #define NORM_YNEG (-2)
94 #define NORM_ZNEG (-3)
95 
96 /*
97  * Regular bit addressing is used: (0..W-1, 0..N-1),
98  * but the bitmap is stored with two cells of zeros all around,
99  * so permissible subscripts run (-2..W+1, -2..N+1).
100  * This eliminates special-case code for the boundary conditions.
101  */
102 #define VOL_XWIDEN 2
103 #define VOL_YWIDEN 2
104 #define VOL_ZWIDEN 2
105 #define VOL(_vip, _xx, _yy, _zz) (_vip)->map[ \
106  (((_zz)+VOL_ZWIDEN) * ((_vip)->ydim + VOL_YWIDEN*2)+ \
107  ((_yy)+VOL_YWIDEN))* ((_vip)->xdim + VOL_XWIDEN*2)+ \
108  (_xx)+VOL_XWIDEN ]
109 
110 #define OK(_vip, _v) ((_v) >= (_vip)->lo && (_v) <= (_vip)->hi)
111 
112 static int rt_vol_normtab[3] = { NORM_XPOS, NORM_YPOS, NORM_ZPOS };
113 
114 
115 /**
116  * Transform the ray into local coordinates of the volume ("ideal space").
117  * Step through the 3-D array, in local coordinates.
118  * Return intersection segments.
119  *
120  */
121 int
122 rt_vol_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
123 {
124  register struct rt_vol_specific *volp =
125  (struct rt_vol_specific *)stp->st_specific;
126  vect_t invdir;
127  double t0; /* in point of cell */
128  double t1; /* out point of cell */
129  double tmax; /* out point of entire grid */
130  vect_t t; /* next t value for XYZ cell plane intersect */
131  vect_t delta; /* spacing of XYZ cell planes along ray */
132  int igrid[3];/* Grid cell coordinates of cell (integerized) */
133  vect_t P; /* hit point */
134  int inside; /* inside/outside a solid flag */
135  int in_axis;
136  int out_axis;
137  int j;
138  struct xray ideal_ray;
139 
140  /* Transform actual ray into ideal space at origin in X-Y plane */
141  MAT4X3PNT(ideal_ray.r_pt, volp->vol_mat, rp->r_pt);
142  MAT4X3VEC(ideal_ray.r_dir, volp->vol_mat, rp->r_dir);
143  rp = &ideal_ray; /* XXX */
144 
145  /* Compute the inverse of the direction cosines */
146  if (!ZERO(rp->r_dir[X])) {
147  invdir[X] = 1.0/rp->r_dir[X];
148  } else {
149  invdir[X] = INFINITY;
150  rp->r_dir[X] = 0.0;
151  }
152  if (!ZERO(rp->r_dir[Y])) {
153  invdir[Y] = 1.0/rp->r_dir[Y];
154  } else {
155  invdir[Y] = INFINITY;
156  rp->r_dir[Y] = 0.0;
157  }
158  if (!ZERO(rp->r_dir[Z])) {
159  invdir[Z] = 1.0/rp->r_dir[Z];
160  } else {
161  invdir[Z] = INFINITY;
162  rp->r_dir[Z] = 0.0;
163  }
164 
165  /* intersect ray with ideal grid rpp */
166  VSETALL(P, 0);
167  if (! rt_in_rpp(rp, invdir, P, volp->vol_large))
168  return 0; /* MISS */
169  VJOIN1(P, rp->r_pt, rp->r_min, rp->r_dir); /* P is hit point */
170  if (RT_G_DEBUG&DEBUG_VOL)VPRINT("vol_large", volp->vol_large);
171  if (RT_G_DEBUG&DEBUG_VOL)VPRINT("vol_origin", volp->vol_origin);
172  if (RT_G_DEBUG&DEBUG_VOL)VPRINT("r_pt", rp->r_pt);
173  if (RT_G_DEBUG&DEBUG_VOL)VPRINT("P", P);
174  if (RT_G_DEBUG&DEBUG_VOL)VPRINT("cellsize", volp->vol_i.cellsize);
175  t0 = rp->r_min;
176  tmax = rp->r_max;
177  if (RT_G_DEBUG&DEBUG_VOL)bu_log("[shoot: r_min=%g, r_max=%g]\n", rp->r_min, rp->r_max);
178 
179  /* find grid cell where ray first hits ideal space bounding RPP */
180  igrid[X] = (P[X] - volp->vol_origin[X]) / volp->vol_i.cellsize[X];
181  igrid[Y] = (P[Y] - volp->vol_origin[Y]) / volp->vol_i.cellsize[Y];
182  igrid[Z] = (P[Z] - volp->vol_origin[Z]) / volp->vol_i.cellsize[Z];
183  if (igrid[X] < 0) {
184  igrid[X] = 0;
185  } else if ((size_t)igrid[X] >= volp->vol_i.xdim) {
186  igrid[X] = volp->vol_i.xdim-1;
187  }
188  if (igrid[Y] < 0) {
189  igrid[Y] = 0;
190  } else if ((size_t)igrid[Y] >= volp->vol_i.ydim) {
191  igrid[Y] = volp->vol_i.ydim-1;
192  }
193  if (igrid[Z] < 0) {
194  igrid[Z] = 0;
195  } else if ((size_t)igrid[Z] >= volp->vol_i.zdim) {
196  igrid[Z] = volp->vol_i.zdim-1;
197  }
198  if (RT_G_DEBUG&DEBUG_VOL)bu_log("igrid=(%d, %d, %d)\n", igrid[X], igrid[Y], igrid[Z]);
199 
200  /* X setup */
201  if (ZERO(rp->r_dir[X])) {
202  t[X] = INFINITY;
203  delta[X] = 0;
204  } else {
205  j = igrid[X];
206  if (rp->r_dir[X] < 0) j++;
207  t[X] = (volp->vol_origin[X] + j*volp->vol_i.cellsize[X] -
208  rp->r_pt[X]) * invdir[X];
209  delta[X] = volp->vol_i.cellsize[X] * fabs(invdir[X]);
210  }
211  /* Y setup */
212  if (ZERO(rp->r_dir[Y])) {
213  t[Y] = INFINITY;
214  delta[Y] = 0;
215  } else {
216  j = igrid[Y];
217  if (rp->r_dir[Y] < 0) j++;
218  t[Y] = (volp->vol_origin[Y] + j*volp->vol_i.cellsize[Y] -
219  rp->r_pt[Y]) * invdir[Y];
220  delta[Y] = volp->vol_i.cellsize[Y] * fabs(invdir[Y]);
221  }
222  /* Z setup */
223  if (ZERO(rp->r_dir[Z])) {
224  t[Z] = INFINITY;
225  delta[Z] = 0;
226  } else {
227  j = igrid[Z];
228  if (rp->r_dir[Z] < 0) j++;
229  t[Z] = (volp->vol_origin[Z] + j*volp->vol_i.cellsize[Z] -
230  rp->r_pt[Z]) * invdir[Z];
231  delta[Z] = volp->vol_i.cellsize[Z] * fabs(invdir[Z]);
232  }
233 
234  /* The delta[] elements *must* be positive, as t must increase */
235  if (RT_G_DEBUG&DEBUG_VOL)bu_log("t[X] = %g, delta[X] = %g\n", t[X], delta[X]);
236  if (RT_G_DEBUG&DEBUG_VOL)bu_log("t[Y] = %g, delta[Y] = %g\n", t[Y], delta[Y]);
237  if (RT_G_DEBUG&DEBUG_VOL)bu_log("t[Z] = %g, delta[Z] = %g\n", t[Z], delta[Z]);
238 
239  /* Find face of entry into first cell -- max initial t value */
240  if (t[X] >= t[Y]) {
241  in_axis = X;
242  t0 = t[X];
243  } else {
244  in_axis = Y;
245  t0 = t[Y];
246  }
247  if (t[Z] > t0) {
248  in_axis = Z;
249  t0 = t[Z];
250  }
251  if (RT_G_DEBUG&DEBUG_VOL)bu_log("Entry axis is %s, t0=%g\n", in_axis==X ? "X" : (in_axis==Y?"Y":"Z"), t0);
252 
253  /* Advance to next exits */
254  t[X] += delta[X];
255  t[Y] += delta[Y];
256  t[Z] += delta[Z];
257 
258  /* Ensure that next exit is after first entrance */
259  if (t[X] < t0) {
260  bu_log("*** advancing t[X]\n");
261  t[X] += delta[X];
262  }
263  if (t[Y] < t0) {
264  bu_log("*** advancing t[Y]\n");
265  t[Y] += delta[Y];
266  }
267  if (t[Z] < t0) {
268  bu_log("*** advancing t[Z]\n");
269  t[Z] += delta[Z];
270  }
271  if (RT_G_DEBUG&DEBUG_VOL) VPRINT("Exit t[]", t);
272 
273  inside = 0;
274 
275  while (t0 < tmax) {
276  int val;
277  struct seg *segp;
278 
279  /* find minimum exit t value */
280  if (t[X] < t[Y]) {
281  if (t[Z] < t[X]) {
282  out_axis = Z;
283  t1 = t[Z];
284  } else {
285  out_axis = X;
286  t1 = t[X];
287  }
288  } else {
289  if (t[Z] < t[Y]) {
290  out_axis = Z;
291  t1 = t[Z];
292  } else {
293  out_axis = Y;
294  t1 = t[Y];
295  }
296  }
297 
298  /* Ray passes through cell igrid[XY] from t0 to t1 */
299  val = VOL(&volp->vol_i, igrid[X], igrid[Y], igrid[Z]);
300  if (RT_G_DEBUG&DEBUG_VOL)bu_log("igrid [%d %d %d] from %g to %g, val=%d\n",
301  igrid[X], igrid[Y], igrid[Z],
302  t0, t1, val);
303  if (RT_G_DEBUG&DEBUG_VOL)bu_log("Exit axis is %s, t[]=(%g, %g, %g)\n",
304  out_axis==X ? "X" : (out_axis==Y?"Y":"Z"),
305  t[X], t[Y], t[Z]);
306 
307  if (t1 <= t0) bu_log("ERROR vol t1=%g < t0=%g\n", t1, t0);
308  if (!inside) {
309  if (OK(&volp->vol_i, (size_t)val)) {
310  /* Handle the transition from vacuum to solid */
311  /* Start of segment (entering a full voxel) */
312  inside = 1;
313 
314  RT_GET_SEG(segp, ap->a_resource);
315  segp->seg_stp = stp;
316  segp->seg_in.hit_dist = t0;
317 
318  /* Compute entry normal */
319  if (rp->r_dir[in_axis] < 0) {
320  /* Go left, entry norm goes right */
321  segp->seg_in.hit_surfno =
322  rt_vol_normtab[in_axis];
323  } else {
324  /* go right, entry norm goes left */
325  segp->seg_in.hit_surfno =
326  (-rt_vol_normtab[in_axis]);
327  }
328  BU_LIST_INSERT(&(seghead->l), &(segp->l));
329  if (RT_G_DEBUG&DEBUG_VOL) bu_log("START t=%g, surfno=%d\n",
330  t0, segp->seg_in.hit_surfno);
331  } else {
332  /* Do nothing, marching through void */
333  }
334  } else {
335  if (OK(&volp->vol_i, (size_t)val)) {
336  /* Do nothing, marching through solid */
337  } else {
338  register struct seg *tail;
339  /* End of segment (now in an empty voxel) */
340  /* Handle transition from solid to vacuum */
341  inside = 0;
342 
343  tail = BU_LIST_LAST(seg, &(seghead->l));
344  tail->seg_out.hit_dist = t0;
345 
346  /* Compute exit normal */
347  if (rp->r_dir[in_axis] < 0) {
348  /* Go left, exit normal goes left */
349  tail->seg_out.hit_surfno =
350  (-rt_vol_normtab[in_axis]);
351  } else {
352  /* go right, exit norm goes right */
353  tail->seg_out.hit_surfno =
354  rt_vol_normtab[in_axis];
355  }
356  if (RT_G_DEBUG&DEBUG_VOL) bu_log("END t=%g, surfno=%d\n",
357  t0, tail->seg_out.hit_surfno);
358  }
359  }
360 
361  /* Take next step */
362  t0 = t1;
363  in_axis = out_axis;
364  t[out_axis] += delta[out_axis];
365  if (rp->r_dir[out_axis] > 0) {
366  igrid[out_axis]++;
367  } else {
368  igrid[out_axis]--;
369  }
370  }
371 
372  if (inside) {
373  register struct seg *tail;
374 
375  /* Close off the final segment */
376  tail = BU_LIST_LAST(seg, &(seghead->l));
377  tail->seg_out.hit_dist = tmax;
378 
379  /* Compute exit normal. Previous out_axis is now in_axis */
380  if (rp->r_dir[in_axis] < 0) {
381  /* Go left, exit normal goes left */
382  tail->seg_out.hit_surfno = (-rt_vol_normtab[in_axis]);
383  } else {
384  /* go right, exit norm goes right */
385  tail->seg_out.hit_surfno = rt_vol_normtab[in_axis];
386  }
387  if (RT_G_DEBUG&DEBUG_VOL) bu_log("closed END t=%g, surfno=%d\n",
388  tmax, tail->seg_out.hit_surfno);
389  }
390 
391  if (BU_LIST_IS_EMPTY(&(seghead->l)))
392  return 0;
393  return 2;
394 }
395 
396 
397 /**
398  * Read in the information from the string solid record.
399  * Then, as a service to the application, read in the bitmap
400  * and set up some of the associated internal variables.
401  */
402 int
403 rt_vol_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
404 {
405  union record *rp;
406  register struct rt_vol_internal *vip;
407  struct bu_vls str = BU_VLS_INIT_ZERO;
408  FILE *fp;
409  int nbytes;
410  size_t y;
411  size_t z;
412  mat_t tmat;
413  size_t ret;
414 
415  if (dbip) RT_CK_DBI(dbip);
416 
417  BU_CK_EXTERNAL(ep);
418  rp = (union record *)ep->ext_buf;
419  if (rp->u_id != DBID_STRSOL) {
420  bu_log("rt_vol_import4: defective strsol record\n");
421  return -1;
422  }
423 
424  RT_CK_DB_INTERNAL(ip);
425  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
426  ip->idb_type = ID_VOL;
427  ip->idb_meth = &OBJ[ID_VOL];
428  BU_ALLOC(ip->idb_ptr, struct rt_vol_internal);
429 
430  vip = (struct rt_vol_internal *)ip->idb_ptr;
431  vip->magic = RT_VOL_INTERNAL_MAGIC;
432 
433  /* Establish defaults */
434  MAT_IDN(vip->mat);
435  vip->lo = 0;
436  vip->hi = 255;
437 
438  /* Default VOL cell size in ideal coordinates is one unit/cell */
439  VSETALL(vip->cellsize, 1);
440 
441  bu_vls_strcpy(&str, rp->ss.ss_args);
442  if (bu_struct_parse(&str, rt_vol_parse, (char *)vip, NULL) < 0) {
443  bu_vls_free(&str);
444  return -2;
445  }
446  bu_vls_free(&str);
447 
448  /* Check for reasonable values */
449  if (vip->file[0] == '\0' || vip->xdim < 1 ||
450  vip->ydim < 1 || vip->zdim < 1 || vip->mat[15] <= 0.0 ||
451  vip->hi > 255) {
452  bu_struct_print("Unreasonable VOL parameters", rt_vol_parse,
453  (char *)vip);
454  return -1;
455  }
456 
457  /* Apply any modeling transforms to get final matrix */
458  if (mat == NULL) mat = bn_mat_identity;
459  bn_mat_mul(tmat, mat, vip->mat);
460  MAT_COPY(vip->mat, tmat);
461 
462  /* Get bit map from .bw(5) file */
463  nbytes = (vip->xdim+VOL_XWIDEN*2)*
464  (vip->ydim+VOL_YWIDEN*2)*
465  (vip->zdim+VOL_ZWIDEN*2);
466  vip->map = (unsigned char *)bu_calloc(1, nbytes, "vol_import4 bitmap");
467 
469  if ((fp = fopen(vip->file, "rb")) == NULL) {
470  perror(vip->file);
471  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
472  return -1;
473  }
474  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
475 
476  /* Because of in-memory padding, read each scanline separately */
477  for (z = 0; z < vip->zdim; z++) {
478  for (y = 0; y < vip->ydim; y++) {
480  ret = fread(&VOL(vip, 0, y, z), vip->xdim, 1, fp); /* res_syscall */
481  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
482  if (ret < 1) {
483  bu_log("rt_vol_import4(%s): Unable to read whole VOL, y=%zu, z=%zu\n",
484  vip->file, y, z);
486  fclose(fp);
487  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
488  return -1;
489  }
490  }
491  }
493  fclose(fp);
494  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
495  return 0;
496 }
497 
498 
499 /**
500  * The name will be added by the caller.
501  */
502 int
503 rt_vol_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
504 {
505  struct rt_vol_internal *vip;
506  struct rt_vol_internal vol; /* scaled version */
507  union record *rec;
508  struct bu_vls str = BU_VLS_INIT_ZERO;
509 
510  if (dbip) RT_CK_DBI(dbip);
511 
512  RT_CK_DB_INTERNAL(ip);
513  if (ip->idb_type != ID_VOL) return -1;
514  vip = (struct rt_vol_internal *)ip->idb_ptr;
515  RT_VOL_CK_MAGIC(vip);
516  vol = *vip; /* struct copy */
517 
518  /* Apply scale factor */
519  vol.mat[15] /= local2mm;
520 
521  BU_CK_EXTERNAL(ep);
522  ep->ext_nbytes = sizeof(union record)*DB_SS_NGRAN;
523  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "vol external");
524  rec = (union record *)ep->ext_buf;
525 
526  bu_vls_struct_print(&str, rt_vol_parse, (char *)&vol);
527 
528  rec->ss.ss_id = DBID_STRSOL;
529  bu_strlcpy(rec->ss.ss_keyword, "vol", sizeof(rec->ss.ss_keyword));
530  bu_strlcpy(rec->ss.ss_args, bu_vls_addr(&str), DB_SS_LEN);
531  bu_vls_free(&str);
532 
533  return 0;
534 }
535 
536 
537 /**
538  * Read in the information from the string solid record.
539  * Then, as a service to the application, read in the bitmap
540  * and set up some of the associated internal variables.
541  */
542 int
543 rt_vol_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
544 {
545  register struct rt_vol_internal *vip;
546  struct bu_vls str = BU_VLS_INIT_ZERO;
547  FILE *fp;
548  int nbytes;
549  size_t y;
550  size_t z;
551  mat_t tmat;
552  size_t ret;
553 
554  if (dbip) RT_CK_DBI(dbip);
555 
556  BU_CK_EXTERNAL(ep);
557 
558  RT_CK_DB_INTERNAL(ip);
559  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
560  ip->idb_type = ID_VOL;
561  ip->idb_meth = &OBJ[ID_VOL];
562  BU_ALLOC(ip->idb_ptr, struct rt_vol_internal);
563 
564  vip = (struct rt_vol_internal *)ip->idb_ptr;
565  vip->magic = RT_VOL_INTERNAL_MAGIC;
566 
567  /* Establish defaults */
568  MAT_IDN(vip->mat);
569  vip->lo = 0;
570  vip->hi = 255;
571 
572  /* Default VOL cell size in ideal coordinates is one unit/cell */
573  VSETALL(vip->cellsize, 1);
574 
575  bu_vls_strncpy(&str, (const char *)ep->ext_buf, ep->ext_nbytes);
576  if (bu_struct_parse(&str, rt_vol_parse, (char *)vip, NULL) < 0) {
577  bu_vls_free(&str);
578  return -2;
579  }
580  bu_vls_free(&str);
581 
582  /* Check for reasonable values */
583  if (vip->file[0] == '\0' || vip->xdim < 1 ||
584  vip->ydim < 1 || vip->zdim < 1 || vip->mat[15] <= 0.0 ||
585  vip->hi > 255) {
586  bu_struct_print("Unreasonable VOL parameters", rt_vol_parse,
587  (char *)vip);
588  return -1;
589  }
590 
591  /* Apply any modeling transforms to get final matrix */
592  if (mat == NULL) mat = bn_mat_identity;
593  bn_mat_mul(tmat, mat, vip->mat);
594  MAT_COPY(vip->mat, tmat);
595 
596  /* Get bit map from .bw(5) file */
597  nbytes = (vip->xdim+VOL_XWIDEN*2)*
598  (vip->ydim+VOL_YWIDEN*2)*
599  (vip->zdim+VOL_ZWIDEN*2);
600  vip->map = (unsigned char *)bu_calloc(1, nbytes, "vol_import4 bitmap");
601 
603  if ((fp = fopen(vip->file, "rb")) == NULL) {
604  perror(vip->file);
605  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
606  return -1;
607  }
608  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
609 
610  /* Because of in-memory padding, read each scanline separately */
611  for (z = 0; z < vip->zdim; z++) {
612  for (y = 0; y < vip->ydim; y++) {
614  ret = fread(&VOL(vip, 0, y, z), vip->xdim, 1, fp); /* res_syscall */
615  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
616  if (ret < 1) {
617  bu_log("rt_vol_import4(%s): Unable to read whole VOL, y=%zu, z=%zu\n",
618  vip->file, y, z);
620  fclose(fp);
621  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
622  return -1;
623  }
624  }
625  }
627  fclose(fp);
628  bu_semaphore_release(BU_SEM_SYSCALL); /* unlock */
629  return 0;
630 }
631 
632 
633 /**
634  * The name will be added by the caller.
635  */
636 int
637 rt_vol_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
638 {
639  struct rt_vol_internal *vip;
640  struct rt_vol_internal vol; /* scaled version */
641  struct bu_vls str = BU_VLS_INIT_ZERO;
642 
643  if (dbip) RT_CK_DBI(dbip);
644 
645  RT_CK_DB_INTERNAL(ip);
646  if (ip->idb_type != ID_VOL) return -1;
647  vip = (struct rt_vol_internal *)ip->idb_ptr;
648  RT_VOL_CK_MAGIC(vip);
649  vol = *vip; /* struct copy */
650 
651  /* Apply scale factor */
652  vol.mat[15] /= local2mm;
653 
654  BU_CK_EXTERNAL(ep);
655 
656  bu_vls_struct_print(&str, rt_vol_parse, (char *)&vol);
657  ep->ext_nbytes = bu_vls_strlen(&str);
658  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "vol external");
659 
660  bu_strlcpy((char *)ep->ext_buf, bu_vls_addr(&str), ep->ext_nbytes);
661  bu_vls_free(&str);
662 
663  return 0;
664 }
665 
666 
667 /**
668  * Make human-readable formatted presentation of this solid.
669  * First line describes type of solid.
670  * Additional lines are indented one tab, and give parameter values.
671  */
672 int
673 rt_vol_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
674 {
675  struct rt_vol_internal *vip = (struct rt_vol_internal *)ip->idb_ptr;
676  register int i;
677  struct bu_vls substr = BU_VLS_INIT_ZERO;
678  vect_t local;
679 
680  RT_VOL_CK_MAGIC(vip);
681 
682  VSCALE(local, vip->cellsize, mm2local);
683  bu_vls_strcat(str, "thresholded volumetric solid (VOL)\n\t");
684 
685  if (!verbose)
686  return 0;
687 
688 /* bu_vls_struct_print(str, rt_vol_parse, (char *)vip);
689  bu_vls_strcat(str, "\n"); */
690 
691  bu_vls_printf(&substr, " file=\"%s\" w=%u n=%u d=%u lo=%u hi=%u size=%g %g %g\n mat=",
692  vip->file,
693  vip->xdim, vip->ydim, vip->zdim, vip->lo, vip->hi,
694  V3INTCLAMPARGS(local));
695  bu_vls_vlscat(str, &substr);
696  for (i = 0; i < 15; i++) {
697  bu_vls_trunc(&substr, 0);
698  bu_vls_printf(&substr, "%g, ", INTCLAMP(vip->mat[i]));
699  bu_vls_vlscat(str, &substr);
700  }
701  bu_vls_trunc(&substr, 0);
702  bu_vls_printf(&substr, "%g\n", INTCLAMP(vip->mat[i]));
703  bu_vls_vlscat(str, &substr);
704 
705  bu_vls_free(&substr);
706 
707  return 0;
708 }
709 
710 
711 /**
712  * Free the storage associated with the rt_db_internal version of this solid.
713  */
714 void
716 {
717  register struct rt_vol_internal *vip;
718 
719  RT_CK_DB_INTERNAL(ip);
720 
721  vip = (struct rt_vol_internal *)ip->idb_ptr;
722  RT_VOL_CK_MAGIC(vip);
723 
724  /* should be stolen by vol_specific, but check just in case */
725  if (vip->map)
726  bu_free((char *)vip->map, "vol bitmap");
727 
728  vip->magic = 0; /* sanity */
729  vip->map = (unsigned char *)0;
730  bu_free((char *)vip, "vol ifree");
731  ip->idb_ptr = ((void *)0); /* sanity */
732 }
733 
734 
735 /**
736  * Calculate bounding RPP for vol
737  */
738 int
739 rt_vol_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol))
740 {
741  register struct rt_vol_internal *vip;
742  vect_t v1, localspace;
743 
744  RT_CK_DB_INTERNAL(ip);
745  vip = (struct rt_vol_internal *)ip->idb_ptr;
746  RT_VOL_CK_MAGIC(vip);
747 
748  /* Find bounding RPP of rotated local RPP */
749  VSETALL(v1, 0);
750  VSET(localspace, vip->xdim*vip->cellsize[0], vip->ydim*vip->cellsize[1], vip->zdim*vip->cellsize[2]);/* type conversion */
751  bn_rotate_bbox((*min), (*max), vip->mat, v1, localspace);
752  return 0;
753 }
754 
755 
756 /**
757  * Returns -
758  * 0 OK
759  * !0 Failure
760  *
761  * Implicit return -
762  * A struct rt_vol_specific is created, and its address is stored
763  * in stp->st_specific for use by rt_vol_shot().
764  */
765 int
766 rt_vol_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
767 {
768  struct rt_vol_internal *vip;
769  register struct rt_vol_specific *volp;
770  vect_t norm;
771  vect_t radvec;
772  vect_t diam;
773 
774  RT_CK_SOLTAB(stp);
775  RT_CK_DB_INTERNAL(ip);
776  if (rtip) RT_CK_RTI(rtip);
777 
778  vip = (struct rt_vol_internal *)ip->idb_ptr;
779  RT_VOL_CK_MAGIC(vip);
780 
781  BU_GET(volp, struct rt_vol_specific);
782  volp->vol_i = *vip; /* struct copy */
783  vip->map = (unsigned char *)0; /* "steal" the bitmap storage */
784 
785  /* build Xform matrix from model(world) to ideal(local) space */
786  bn_mat_inv(volp->vol_mat, vip->mat);
787 
788  /* Pre-compute the necessary normals. Rotate only. */
789  VSET(norm, 1, 0, 0);
790  MAT3X3VEC(volp->vol_xnorm, vip->mat, norm);
791  VSET(norm, 0, 1, 0);
792  MAT3X3VEC(volp->vol_ynorm, vip->mat, norm);
793  VSET(norm, 0, 0, 1);
794  MAT3X3VEC(volp->vol_znorm, vip->mat, norm);
795 
796  stp->st_specific = (void *)volp;
797 
798  /* Find bounding RPP of rotated local RPP */
799  if (rt_vol_bbox(ip, &(stp->st_min), &(stp->st_max), &rtip->rti_tol)) return 1;
800  VSET(volp->vol_large,
801  volp->vol_i.xdim*vip->cellsize[0], volp->vol_i.ydim*vip->cellsize[1], volp->vol_i.zdim*vip->cellsize[2]);/* type conversion */
802 
803  /* for now, VOL origin in ideal coordinates is at origin */
804  VSETALL(volp->vol_origin, 0);
805  VADD2(volp->vol_large, volp->vol_large, volp->vol_origin);
806 
807  VSUB2(diam, stp->st_max, stp->st_min);
808  VADD2SCALE(stp->st_center, stp->st_min, stp->st_max, 0.5);
809  VSCALE(radvec, diam, 0.5);
810  stp->st_aradius = stp->st_bradius = MAGNITUDE(radvec);
811 
812  return 0; /* OK */
813 }
814 
815 
816 void
817 rt_vol_print(register const struct soltab *stp)
818 {
819  register const struct rt_vol_specific *volp =
820  (struct rt_vol_specific *)stp->st_specific;
821 
822  bu_log("vol file = %s\n", volp->vol_i.file);
823  bu_log("dimensions = (%u, %u, %u)\n",
824  volp->vol_i.xdim, volp->vol_i.ydim,
825  volp->vol_i.zdim);
826  VPRINT("model cellsize", volp->vol_i.cellsize);
827  VPRINT("model grid origin", volp->vol_origin);
828 }
829 
830 
831 /**
832  * Given one ray distance, return the normal and
833  * entry/exit point.
834  * This is mostly a matter of translating the stored
835  * code into the proper normal.
836  */
837 void
838 rt_vol_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
839 {
840  register struct rt_vol_specific *volp =
841  (struct rt_vol_specific *)stp->st_specific;
842 
843  VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
844 
845  switch (hitp->hit_surfno) {
846  case NORM_XPOS:
847  VMOVE(hitp->hit_normal, volp->vol_xnorm);
848  break;
849  case NORM_XNEG:
850  VREVERSE(hitp->hit_normal, volp->vol_xnorm);
851  break;
852 
853  case NORM_YPOS:
854  VMOVE(hitp->hit_normal, volp->vol_ynorm);
855  break;
856  case NORM_YNEG:
857  VREVERSE(hitp->hit_normal, volp->vol_ynorm);
858  break;
859 
860  case NORM_ZPOS:
861  VMOVE(hitp->hit_normal, volp->vol_znorm);
862  break;
863  case NORM_ZNEG:
864  VREVERSE(hitp->hit_normal, volp->vol_znorm);
865  break;
866 
867  default:
868  bu_log("rt_vol_norm(%s): surfno=%d bad\n",
869  stp->st_name, hitp->hit_surfno);
870  VSETALL(hitp->hit_normal, 0);
871  break;
872  }
873 }
874 
875 
876 /**
877  * Everything has sharp edges. This makes things easy.
878  */
879 void
880 rt_vol_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
881 {
882  if (!cvp || !hitp)
883  return;
884  RT_CK_HIT(hitp);
885  if (stp) RT_CK_SOLTAB(stp);
886 
887  bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal);
888  cvp->crv_c1 = cvp->crv_c2 = 0;
889 }
890 
891 
892 /**
893  * Map the hit point in 2-D into the range 0..1
894  * untransformed X becomes U, and Y becomes V.
895  */
896 void
897 rt_vol_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
898 {
899  if (ap) RT_CK_APPLICATION(ap);
900  if (stp) RT_CK_SOLTAB(stp);
901  if (hitp) RT_CK_SOLTAB(stp);
902  if (!uvp)
903  return;
904 
905  /* XXX uv should be xy in ideal space */
906 }
907 
908 
909 void
910 rt_vol_free(struct soltab *stp)
911 {
912  register struct rt_vol_specific *volp =
913  (struct rt_vol_specific *)stp->st_specific;
914 
915  /* specific steals map from vip, release here */
916  if (volp->vol_i.map) {
917  bu_free((char *)volp->vol_i.map, "vol_map");
918  volp->vol_i.map = NULL; /* sanity */
919  }
920  BU_PUT(volp, struct rt_vol_specific);
921 }
922 
923 
924 int
925 rt_vol_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
926 {
927  register struct rt_vol_internal *vip;
928  size_t x, y, z;
929  register short v1, v2;
930  point_t a, b, c, d;
931 
932  BU_CK_LIST_HEAD(vhead);
933  RT_CK_DB_INTERNAL(ip);
934  vip = (struct rt_vol_internal *)ip->idb_ptr;
935  RT_VOL_CK_MAGIC(vip);
936 
937  /*
938  * Scan across in Z & X. For each X position, scan down Y,
939  * looking for the longest run of edge.
940  */
941  for (z=-1; z<=vip->zdim; z++) {
942  for (x=-1; x<=vip->xdim; x++) {
943  for (y=-1; y<=vip->ydim; y++) {
944  v1 = VOL(vip, x, y, z);
945  v2 = VOL(vip, x+1, y, z);
946  if (OK(vip, (size_t)v1) == OK(vip, (size_t)v2)) continue;
947  /* Note start point, continue scan */
948  VSET(a, x+0.5, y-0.5, z-0.5);
949  VSET(b, x+0.5, y-0.5, z+0.5);
950  for (++y; y<=vip->ydim; y++) {
951  v1 = VOL(vip, x, y, z);
952  v2 = VOL(vip, x+1, y, z);
953  if (OK(vip, (size_t)v1) == OK(vip, (size_t)v2))
954  break;
955  }
956  /* End of run of edge. One cell beyond. */
957  VSET(c, x+0.5, y-0.5, z+0.5);
958  VSET(d, x+0.5, y-0.5, z-0.5);
959  rt_vol_plate(a, b, c, d, vip->mat, vhead, vip);
960  }
961  }
962  }
963 
964  /*
965  * Scan up in Z & Y. For each Y position, scan across X
966  */
967  for (z=-1; z<=vip->zdim; z++) {
968  for (y=-1; y<=vip->ydim; y++) {
969  for (x=-1; x<=vip->xdim; x++) {
970  v1 = VOL(vip, x, y, z);
971  v2 = VOL(vip, x, y+1, z);
972  if (OK(vip, (size_t)v1) == OK(vip, (size_t)v2)) continue;
973  /* Note start point, continue scan */
974  VSET(a, x-0.5, y+0.5, z-0.5);
975  VSET(b, x-0.5, y+0.5, z+0.5);
976  for (++x; x<=vip->xdim; x++) {
977  v1 = VOL(vip, x, y, z);
978  v2 = VOL(vip, x, y+1, z);
979  if (OK(vip, (size_t)v1) == OK(vip, (size_t)v2))
980  break;
981  }
982  /* End of run of edge. One cell beyond */
983  VSET(c, (x-0.5), (y+0.5), (z+0.5));
984  VSET(d, (x-0.5), (y+0.5), (z-0.5));
985  rt_vol_plate(a, b, c, d, vip->mat, vhead, vip);
986  }
987  }
988  }
989 
990  /*
991  * Scan across in Y & X. For each X position pair edge, scan up Z.
992  */
993  for (x=-1; x<=vip->xdim; x++) {
994  for (z=-1; z<=vip->zdim; z++) {
995  for (y=-1; y<=vip->ydim; y++) {
996  v1 = VOL(vip, x, y, z);
997  v2 = VOL(vip, x, y, z+1);
998  if (OK(vip, (size_t)v1) == OK(vip, (size_t)v2)) continue;
999  /* Note start point, continue scan */
1000  VSET(a, (x-0.5), (y-0.5), (z+0.5));
1001  VSET(b, (x+0.5), (y-0.5), (z+0.5));
1002  for (++y; y<=vip->ydim; y++) {
1003  v1 = VOL(vip, x, y, z);
1004  v2 = VOL(vip, x, y, z+1);
1005  if (OK(vip, (size_t)v1) == OK(vip, (size_t)v2))
1006  break;
1007  }
1008  /* End of run of edge. One cell beyond */
1009  VSET(c, (x+0.5), (y-0.5), (z+0.5));
1010  VSET(d, (x-0.5), (y-0.5), (z+0.5));
1011  rt_vol_plate(a, b, c, d, vip->mat, vhead, vip);
1012  }
1013  }
1014  }
1015  return 0;
1016 }
1017 
1018 
1019 void
1020 rt_vol_plate(fastf_t *a, fastf_t *b, fastf_t *c, fastf_t *d, register fastf_t *mat, register struct bu_list *vhead, register struct rt_vol_internal *vip)
1021 {
1022  point_t s; /* scaled original point */
1023  point_t arot, prot;
1024 
1025  BU_CK_LIST_HEAD(vhead);
1026 
1027  VELMUL(s, vip->cellsize, a);
1028  MAT4X3PNT(arot, mat, s);
1029  RT_ADD_VLIST(vhead, arot, BN_VLIST_LINE_MOVE);
1030 
1031  VELMUL(s, vip->cellsize, b);
1032  MAT4X3PNT(prot, mat, s);
1033  RT_ADD_VLIST(vhead, prot, BN_VLIST_LINE_DRAW);
1034 
1035  VELMUL(s, vip->cellsize, c);
1036  MAT4X3PNT(prot, mat, s);
1037  RT_ADD_VLIST(vhead, prot, BN_VLIST_LINE_DRAW);
1038 
1039  VELMUL(s, vip->cellsize, d);
1040  MAT4X3PNT(prot, mat, s);
1041  RT_ADD_VLIST(vhead, prot, BN_VLIST_LINE_DRAW);
1042 
1043  RT_ADD_VLIST(vhead, arot, BN_VLIST_LINE_DRAW);
1044 }
1045 
1046 
1047 int
1048 rt_vol_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
1049 {
1050  struct rt_vol_internal *vip;
1051  register size_t x, y, z;
1052  int i;
1053  struct shell *s;
1054  struct vertex *verts[4];
1055  struct faceuse *fu;
1056  struct model *m_tmp;
1057  struct nmgregion *r_tmp;
1058 
1059  NMG_CK_MODEL(m);
1060  BN_CK_TOL(tol);
1061  RT_CK_TESS_TOL(ttol);
1062 
1063  RT_CK_DB_INTERNAL(ip);
1064  vip = (struct rt_vol_internal *)ip->idb_ptr;
1065  RT_VOL_CK_MAGIC(vip);
1066 
1067  /* make region, shell, vertex */
1068  m_tmp = nmg_mm();
1069  r_tmp = nmg_mrsv(m_tmp);
1070  s = BU_LIST_FIRST(shell, &r_tmp->s_hd);
1071 
1072  for (x = 0; x < vip->xdim; x++) {
1073  for (y = 0; y < vip->ydim; y++) {
1074  for (z = 0; z < vip->zdim; z++) {
1075  point_t pt, pt1;
1076 
1077  /* skip empty cells */
1078  if (!OK(vip, VOL(vip, x, y, z)))
1079  continue;
1080 
1081  /* check neighboring cells, make a face where needed */
1082 
1083  /* check z+1 */
1084  if (!OK(vip, VOL(vip, x, y, z+1))) {
1085  for (i = 0; i < 4; i++)
1086  verts[i] = (struct vertex *)NULL;
1087 
1088  fu = nmg_cface(s, verts, 4);
1089 
1090  VSET(pt, x+.5, y-.5, z+.5);
1091  VELMUL(pt1, vip->cellsize, pt);
1092  MAT4X3PNT(pt, vip->mat, pt1);
1093  nmg_vertex_gv(verts[0], pt);
1094  VSET(pt, x+.5, y+.5, z+.5);
1095  VELMUL(pt1, vip->cellsize, pt);
1096  MAT4X3PNT(pt, vip->mat, pt1);
1097  nmg_vertex_gv(verts[1], pt);
1098  VSET(pt, x-.5, y+.5, z+.5);
1099  VELMUL(pt1, vip->cellsize, pt);
1100  MAT4X3PNT(pt, vip->mat, pt1);
1101  nmg_vertex_gv(verts[2], pt);
1102  VSET(pt, x-.5, y-.5, z+.5);
1103  VELMUL(pt1, vip->cellsize, pt);
1104  MAT4X3PNT(pt, vip->mat, pt1);
1105  nmg_vertex_gv(verts[3], pt);
1106 
1107  if (nmg_fu_planeeqn(fu, tol))
1108  goto fail;
1109  }
1110 
1111  /* check z-1 */
1112  if (!OK(vip, VOL(vip, x, y, z-1))) {
1113  for (i = 0; i < 4; i++)
1114  verts[i] = (struct vertex *)NULL;
1115 
1116  fu = nmg_cface(s, verts, 4);
1117 
1118  VSET(pt, x+.5, y-.5, z-.5);
1119  VELMUL(pt1, vip->cellsize, pt);
1120  MAT4X3PNT(pt, vip->mat, pt1);
1121  nmg_vertex_gv(verts[3], pt);
1122  VSET(pt, x+.5, y+.5, z-.5);
1123  VELMUL(pt1, vip->cellsize, pt);
1124  MAT4X3PNT(pt, vip->mat, pt1);
1125  nmg_vertex_gv(verts[2], pt);
1126  VSET(pt, x-.5, y+.5, z-.5);
1127  VELMUL(pt1, vip->cellsize, pt);
1128  MAT4X3PNT(pt, vip->mat, pt1);
1129  nmg_vertex_gv(verts[1], pt);
1130  VSET(pt, x-.5, y-.5, z-.5);
1131  VELMUL(pt1, vip->cellsize, pt);
1132  MAT4X3PNT(pt, vip->mat, pt1);
1133  nmg_vertex_gv(verts[0], pt);
1134 
1135  if (nmg_fu_planeeqn(fu, tol))
1136  goto fail;
1137  }
1138 
1139  /* check y+1 */
1140  if (!OK(vip, VOL(vip, x, y+1, z))) {
1141  for (i = 0; i < 4; i++)
1142  verts[i] = (struct vertex *)NULL;
1143 
1144  fu = nmg_cface(s, verts, 4);
1145 
1146  VSET(pt, x+.5, y+.5, z+.5);
1147  VELMUL(pt1, vip->cellsize, pt);
1148  MAT4X3PNT(pt, vip->mat, pt1);
1149  nmg_vertex_gv(verts[0], pt);
1150  VSET(pt, x+.5, y+.5, z-.5);
1151  VELMUL(pt1, vip->cellsize, pt);
1152  MAT4X3PNT(pt, vip->mat, pt1);
1153  nmg_vertex_gv(verts[1], pt);
1154  VSET(pt, x-.5, y+.5, z-.5);
1155  VELMUL(pt1, vip->cellsize, pt);
1156  MAT4X3PNT(pt, vip->mat, pt1);
1157  nmg_vertex_gv(verts[2], pt);
1158  VSET(pt, x-.5, y+.5, z+.5);
1159  VELMUL(pt1, vip->cellsize, pt);
1160  MAT4X3PNT(pt, vip->mat, pt1);
1161  nmg_vertex_gv(verts[3], pt);
1162 
1163  if (nmg_fu_planeeqn(fu, tol))
1164  goto fail;
1165  }
1166 
1167  /* check y-1 */
1168  if (!OK(vip, VOL(vip, x, y-1, z))) {
1169  for (i = 0; i < 4; i++)
1170  verts[i] = (struct vertex *)NULL;
1171 
1172  fu = nmg_cface(s, verts, 4);
1173 
1174  VSET(pt, x+.5, y-.5, z+.5);
1175  VELMUL(pt1, vip->cellsize, pt);
1176  MAT4X3PNT(pt, vip->mat, pt1);
1177  nmg_vertex_gv(verts[3], pt);
1178  VSET(pt, x+.5, y-.5, z-.5);
1179  VELMUL(pt1, vip->cellsize, pt);
1180  MAT4X3PNT(pt, vip->mat, pt1);
1181  nmg_vertex_gv(verts[2], pt);
1182  VSET(pt, x-.5, y-.5, z-.5);
1183  VELMUL(pt1, vip->cellsize, pt);
1184  MAT4X3PNT(pt, vip->mat, pt1);
1185  nmg_vertex_gv(verts[1], pt);
1186  VSET(pt, x-.5, y-.5, z+.5);
1187  VELMUL(pt1, vip->cellsize, pt);
1188  MAT4X3PNT(pt, vip->mat, pt1);
1189  nmg_vertex_gv(verts[0], pt);
1190 
1191  if (nmg_fu_planeeqn(fu, tol))
1192  goto fail;
1193  }
1194 
1195  /* check x+1 */
1196  if (!OK(vip, VOL(vip, x+1, y, z))) {
1197  for (i = 0; i < 4; i++)
1198  verts[i] = (struct vertex *)NULL;
1199 
1200  fu = nmg_cface(s, verts, 4);
1201 
1202  VSET(pt, x+.5, y-.5, z-.5);
1203  VELMUL(pt1, vip->cellsize, pt);
1204  MAT4X3PNT(pt, vip->mat, pt1);
1205  nmg_vertex_gv(verts[0], pt);
1206  VSET(pt, x+.5, y+.5, z-.5);
1207  VELMUL(pt1, vip->cellsize, pt);
1208  MAT4X3PNT(pt, vip->mat, pt1);
1209  nmg_vertex_gv(verts[1], pt);
1210  VSET(pt, x+.5, y+.5, z+.5);
1211  VELMUL(pt1, vip->cellsize, pt);
1212  MAT4X3PNT(pt, vip->mat, pt1);
1213  nmg_vertex_gv(verts[2], pt);
1214  VSET(pt, x+.5, y-.5, z+.5);
1215  VELMUL(pt1, vip->cellsize, pt);
1216  MAT4X3PNT(pt, vip->mat, pt1);
1217  nmg_vertex_gv(verts[3], pt);
1218 
1219  if (nmg_fu_planeeqn(fu, tol))
1220  goto fail;
1221  }
1222 
1223  /* check x-1 */
1224  if (!OK(vip, VOL(vip, x-1, y, z))) {
1225  for (i = 0; i < 4; i++)
1226  verts[i] = (struct vertex *)NULL;
1227 
1228  fu = nmg_cface(s, verts, 4);
1229 
1230  VSET(pt, x-.5, y-.5, z-.5);
1231  VELMUL(pt1, vip->cellsize, pt);
1232  MAT4X3PNT(pt, vip->mat, pt1);
1233  nmg_vertex_gv(verts[3], pt);
1234  VSET(pt, x-.5, y+.5, z-.5);
1235  VELMUL(pt1, vip->cellsize, pt);
1236  MAT4X3PNT(pt, vip->mat, pt1);
1237  nmg_vertex_gv(verts[2], pt);
1238  VSET(pt, x-.5, y+.5, z+.5);
1239  VELMUL(pt1, vip->cellsize, pt);
1240  MAT4X3PNT(pt, vip->mat, pt1);
1241  nmg_vertex_gv(verts[1], pt);
1242  VSET(pt, x-.5, y-.5, z+.5);
1243  VELMUL(pt1, vip->cellsize, pt);
1244  MAT4X3PNT(pt, vip->mat, pt1);
1245  nmg_vertex_gv(verts[0], pt);
1246 
1247  if (nmg_fu_planeeqn(fu, tol))
1248  goto fail;
1249  }
1250  }
1251  }
1252  }
1253 
1254  nmg_region_a(r_tmp, tol);
1255 
1256  /* fuse model */
1257  nmg_model_fuse(m_tmp, tol);
1258 
1259  /* simplify shell */
1260  nmg_shell_coplanar_face_merge(s, tol, 1);
1261 
1262  /* kill snakes */
1263  for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
1264  struct loopuse *lu;
1265 
1266  NMG_CK_FACEUSE(fu);
1267 
1268  if (fu->orientation != OT_SAME)
1269  continue;
1270 
1271  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd))
1272  (void)nmg_kill_snakes(lu);
1273  }
1274 
1275  (void)nmg_unbreak_region_edges((uint32_t *)(&s->l));
1276 
1277  (void)nmg_mark_edges_real((uint32_t *)&s->l);
1278 
1279  nmg_merge_models(m, m_tmp);
1280  *r = r_tmp;
1281 
1282  return 0;
1283 
1284 fail:
1285  nmg_km(m_tmp);
1286  *r = (struct nmgregion *)NULL;
1287 
1288  return -1;
1289 }
1290 
1291 
1292 int
1293 rt_vol_params(struct pc_pc_set *UNUSED(ps), const struct rt_db_internal *ip)
1294 {
1295  if (ip) RT_CK_DB_INTERNAL(ip);
1296 
1297  return 0; /* OK */
1298 }
1299 
1300 
1301 void
1302 rt_vol_centroid(point_t *cent, const struct rt_db_internal *ip)
1303 {
1304  register struct rt_vol_internal *vip;
1305  size_t x, y, z;
1306  size_t cnt;
1307  fastf_t x_tot, y_tot, z_tot;
1308  point_t p;
1309 
1310  RT_CK_DB_INTERNAL(ip);
1311  vip = (struct rt_vol_internal *)ip->idb_ptr;
1312  RT_VOL_CK_MAGIC(vip);
1313 
1314  cnt = 0;
1315  x_tot = y_tot = z_tot = 0.0;
1316 
1317  for (x = 0; x < vip->xdim; x++) {
1318  for (y = 0; y < vip->ydim; y++) {
1319  for (z = 0; z < vip->zdim; z++) {
1320  if (OK(vip, VOL(vip, x, y, z))) {
1321  x_tot += (x+.5) * (vip->cellsize[X]);
1322  y_tot += (y+.5) * (vip->cellsize[Y]);
1323  z_tot += (z+.5) * (vip->cellsize[Z]);
1324  cnt++;
1325  }
1326  }
1327  }
1328  }
1329 
1330  p[X]=x_tot/cnt;
1331  p[Y]=y_tot/cnt;
1332  p[Z]=z_tot/cnt;
1333 
1334  MAT4X3PNT(*cent, vip->mat, p);
1335 }
1336 
1337 
1338 /*
1339  * Computes the surface area of a volume by transforming each of the vertices by
1340  * the matrix and then summing the area of the faces of each cell necessary.
1341  * The vertices are numbered from left to right, front to back, bottom to top.
1342  */
1343 void
1344 rt_vol_surf_area(fastf_t *area, const struct rt_db_internal *ip)
1345 {
1346  struct rt_vol_internal *vip;
1347  unsigned int x, y, z;
1348  point_t x0, x1, x2, x3, x4, x5, x6, x7;
1349  point_t _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7;
1350  vect_t d3_0, d2_1, d7_4, d6_5, d6_0, d4_2, d4_1, d5_0, d5_3, d7_1, d7_2, d6_3, _cross;
1351  fastf_t _x, _y, _z, det, _area = 0.0;
1352 
1353  if (area == NULL || ip == NULL) return;
1354  RT_CK_DB_INTERNAL(ip);
1355  vip = (struct rt_vol_internal *)ip->idb_ptr;
1356  RT_VOL_CK_MAGIC(vip);
1357 
1358  det = fabs(bn_mat_determinant(vip->mat));
1359  if (EQUAL(det, 0.0)) {
1360  *area = -1.0;
1361  return;
1362  }
1363 
1364  for (x = 0; x < vip->xdim; x++) {
1365  for (y = 0; y < vip->ydim; y++) {
1366  for (z = 0; z < vip->zdim; z++) {
1367  if (OK(vip, VOL(vip, x, y, z))) {
1368  _x = (fastf_t)x;
1369  _y = (fastf_t)y;
1370  _z = (fastf_t)z;
1371 
1372  VSET(_x0, _x - 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1373  VSET(_x1, _x + 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1374  VSET(_x2, _x - 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1375  VSET(_x3, _x + 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1376  VSET(_x4, _x - 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1377  VSET(_x5, _x + 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1378  VSET(_x6, _x - 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1379  VSET(_x7, _x + 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1380 
1381  MAT4X3PNT(x0, vip->mat, _x0);
1382  MAT4X3PNT(x1, vip->mat, _x1);
1383  MAT4X3PNT(x2, vip->mat, _x2);
1384  MAT4X3PNT(x3, vip->mat, _x3);
1385  MAT4X3PNT(x4, vip->mat, _x4);
1386  MAT4X3PNT(x5, vip->mat, _x5);
1387  MAT4X3PNT(x6, vip->mat, _x6);
1388  MAT4X3PNT(x7, vip->mat, _x7);
1389 
1390  if (!OK(vip, VOL(vip, x + 1, y, z))) {
1391  VSUB2(d5_3, x5, x3);
1392  VSUB2(d7_1, x7, x1);
1393  VCROSS(_cross, d5_3, d7_1);
1394  _area += 0.5 * MAGNITUDE(_cross);
1395  }
1396  if (!OK(vip, VOL(vip, x - 1, y, z))) {
1397  VSUB2(d6_0, x6, x0);
1398  VSUB2(d4_2, x4, x2);
1399  VCROSS(_cross, d6_0, d4_2);
1400  _area += 0.5 * MAGNITUDE(_cross);
1401  }
1402 
1403  if (!OK(vip, VOL(vip, x, y + 1, z))) {
1404  VSUB2(d7_2, x7, x2);
1405  VSUB2(d6_3, x6, x3);
1406  VCROSS(_cross, d7_2, d6_3);
1407  _area += 0.5 * MAGNITUDE(_cross);
1408  }
1409  if (!OK(vip, VOL(vip, x, y - 1, z))) {
1410  VSUB2(d4_1, x4, x1);
1411  VSUB2(d5_0, x5, x0);
1412  VCROSS(_cross, d4_1, d5_0);
1413  _area += 0.5 * MAGNITUDE(_cross);
1414  }
1415 
1416  if (!OK(vip, VOL(vip, x, y, z + 1))) {
1417  VSUB2(d3_0, x3, x0);
1418  VSUB2(d2_1, x2, x1);
1419  VCROSS(_cross, d3_0, d2_1);
1420  _area += 0.5 * MAGNITUDE(_cross);
1421  }
1422  if (!OK(vip, VOL(vip, x, y, z - 1))) {
1423  VSUB2(d7_4, x7, x4);
1424  VSUB2(d6_5, x6, x5);
1425  VCROSS(_cross, d7_4, d6_5);
1426  _area += 0.5 * MAGNITUDE(_cross);
1427  }
1428  }
1429  }
1430  }
1431  }
1432  *area = _area;
1433 }
1434 
1435 
1436 /*
1437  * A paper at http://www.osti.gov/scitech/servlets/purl/632793 gives a method
1438  * for calculating the volume of hexahedrens from the eight vertices.
1439  *
1440  * The eight vertices are calculated, then transformed by the matrix and the
1441  * volume calculated from that.
1442  */
1443 void
1444 rt_vol_volume(fastf_t *volume, const struct rt_db_internal *ip)
1445 {
1446  struct rt_vol_internal *vip;
1447  unsigned int x, y, z;
1448  point_t x0, x1, x2, x3, x4, x5, x6, x7;
1449  point_t _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7;
1450  vect_t d7_0, d1_0, d3_5, d4_0, d5_6, d2_0, d6_3, cross1, cross2, cross3;
1451  fastf_t _x, _y, _z, det, _vol = 0.0;
1452 
1453  if (volume == NULL || ip == NULL) return;
1454  RT_CK_DB_INTERNAL(ip);
1455  vip = (struct rt_vol_internal *)ip->idb_ptr;
1456  RT_VOL_CK_MAGIC(vip);
1457 
1458  det = fabs(bn_mat_determinant(vip->mat));
1459  if (EQUAL(det, 0.0)) {
1460  *volume = -1.0;
1461  return;
1462  }
1463 
1464  for (x = 0; x < vip->xdim; x++) {
1465  for (y = 0; y < vip->ydim; y++) {
1466  for (z = 0; z < vip->zdim; z++) {
1467  if (OK(vip, VOL(vip, x, y, z))) {
1468  _x = (fastf_t)x;
1469  _y = (fastf_t)y;
1470  _z = (fastf_t)z;
1471 
1472  VSET(_x0, _x - 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1473  VSET(_x1, _x + 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1474  VSET(_x2, _x - 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1475  VSET(_x3, _x + 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z - 0.5 * vip->cellsize[Z]);
1476  VSET(_x4, _x - 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1477  VSET(_x5, _x + 0.5 * vip->cellsize[X], _y - 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1478  VSET(_x6, _x - 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1479  VSET(_x7, _x + 0.5 * vip->cellsize[X], _y + 0.5 * vip->cellsize[Y], _z + 0.5 * vip->cellsize[Z]);
1480 
1481  MAT4X3PNT(x0, vip->mat, _x0);
1482  MAT4X3PNT(x1, vip->mat, _x1);
1483  MAT4X3PNT(x2, vip->mat, _x2);
1484  MAT4X3PNT(x3, vip->mat, _x3);
1485  MAT4X3PNT(x4, vip->mat, _x4);
1486  MAT4X3PNT(x5, vip->mat, _x5);
1487  MAT4X3PNT(x6, vip->mat, _x6);
1488  MAT4X3PNT(x7, vip->mat, _x7);
1489 
1490  VSUB2(d7_0, x7, x0);
1491  VSUB2(d1_0, x1, x0);
1492  VSUB2(d3_5, x3, x5);
1493  VCROSS(cross1, d1_0, d3_5);
1494 
1495  VSUB2(d4_0, x4, x0);
1496  VSUB2(d5_6, x5, x6);
1497  VCROSS(cross2, d4_0, d5_6);
1498 
1499  VSUB2(d2_0, x2, x0);
1500  VSUB2(d6_3, x6, x3);
1501  VCROSS(cross3, d2_0, d6_3);
1502 
1503  _vol += (1.0/6.0) * (VDOT(d7_0, cross1) + VDOT(d7_0, cross2) + VDOT(d7_0, cross3));
1504  }
1505  }
1506  }
1507  }
1508  *volume = fabs(_vol);
1509 }
1510 
1511 
1512 /*
1513  * Local Variables:
1514  * mode: C
1515  * tab-width: 8
1516  * indent-tabs-mode: t
1517  * c-file-style: "stroustrup"
1518  * End:
1519  * ex: shiftwidth=4 tabstop=8
1520  */
Definition: db_flip.c:35
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
Definition: raytrace.h:800
int nmg_model_fuse(struct model *m, const struct bn_tol *tol)
Definition: nmg_fuse.c:1919
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
struct faceuse * nmg_cface(struct shell *s, struct vertex **verts, int n)
Definition: nmg_mod.c:1130
struct hit seg_in
IN information.
Definition: raytrace.h:370
int nmg_unbreak_region_edges(uint32_t *magic_p)
Definition: nmg_misc.c:4650
Definition: list.h:118
int nmg_fu_planeeqn(struct faceuse *fu, const struct bn_tol *tol)
Definition: nmg_mod.c:1311
fastf_t bn_mat_determinant(const mat_t m)
Definition: mat.c:1117
#define BU_LIST_LAST(structure, hp)
Definition: list.h:306
vect_t vol_znorm
Definition: vol.c:58
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
#define RT_CK_RTI(_p)
Definition: raytrace.h:1833
#define VOL_XWIDEN
Definition: vol.c:102
vect_t crv_pdir
Principle direction.
Definition: raytrace.h:307
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
struct soltab * seg_stp
pointer back to soltab
Definition: raytrace.h:372
if lu s
Definition: nmg_mod.c:3860
vect_t vol_ynorm
Definition: vol.c:57
void bn_rotate_bbox(point_t omin, point_t omax, const mat_t mat, const point_t imin, const point_t imax)
Transform a bounding box (RPP) by the given 4x4 matrix. There are 8 corners to the bounding RPP...
int rt_vol_params(struct pc_pc_set *ps, const struct rt_db_internal *ip)
Definition: vol.c:1293
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
lu
Definition: nmg_mod.c:3855
#define VSET(a, b, c, d)
Definition: color.c:53
#define VSETALL(a, s)
Definition: color.c:54
Definition: raytrace.h:215
#define OK(_vip, _v)
Definition: vol.c:110
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
#define NORM_XPOS
Definition: vol.c:91
Definition: pc.h:108
Definition: raytrace.h:368
int rt_vol_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
Definition: vol.c:673
Definition: raytrace.h:248
void nmg_vertex_gv(struct vertex *v, const fastf_t *pt)
Definition: nmg_mk.c:1668
#define VOL_O(m)
Definition: vol.c:65
void rt_vol_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
Definition: vol.c:838
fastf_t st_aradius
Radius of APPROXIMATING sphere.
Definition: raytrace.h:433
void bu_vls_strncpy(struct bu_vls *vp, const char *s, size_t n)
Definition: vls.c:339
Header file for the BRL-CAD common definitions.
void rt_vol_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
Definition: vol.c:897
void rt_vol_plate(point_t a, point_t b, point_t c, point_t d, mat_t mat, struct bu_list *vhead, struct rt_vol_internal *vip)
#define NORM_ZNEG
Definition: vol.c:94
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
int rt_in_rpp(struct xray *rp, const fastf_t *invdir, const fastf_t *min, const fastf_t *max)
#define NORM_YNEG
Definition: vol.c:93
struct bu_list l
Definition: raytrace.h:369
#define ID_VOL
3-D Volume
Definition: raytrace.h:471
void rt_vol_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
Definition: vol.c:880
void bu_struct_print(const char *title, const struct bu_structparse *parsetab, const char *base)
Definition: parse.c:1221
const struct bu_structparse rt_vol_parse[]
Definition: vol.c:67
if(share_geom)
Definition: nmg_mod.c:3829
int idb_major_type
Definition: raytrace.h:192
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
Definition: color.c:49
#define NORM_ZPOS
Definition: vol.c:89
int rt_vol_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *tol)
Definition: vol.c:739
int rt_vol_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: vol.c:766
#define NORM_YPOS
Definition: vol.c:90
#define RT_G_DEBUG
Definition: raytrace.h:1718
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
void nmg_shell_coplanar_face_merge(struct shell *s, const struct bn_tol *tol, const int simplify)
Definition: nmg_mod.c:93
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
void rt_vol_surf_area(fastf_t *area, const struct rt_db_internal *ip)
Definition: vol.c:1344
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
fastf_t st_bradius
Radius of BOUNDING sphere.
Definition: raytrace.h:434
void rt_vol_print(register const struct soltab *stp)
Definition: vol.c:817
fastf_t crv_c2
curvature in other direction
Definition: raytrace.h:309
#define RT_CK_HIT(_p)
Definition: raytrace.h:259
int rt_vol_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: vol.c:543
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
void bn_mat_inv(mat_t output, const mat_t input)
#define RT_CK_TESS_TOL(_p)
Definition: raytrace.h:184
int rt_vol_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol, const struct rt_view_info *info)
Definition: vol.c:925
uint8_t * ext_buf
Definition: parse.h:216
void nmg_km(struct model *m)
Definition: nmg_mk.c:1634
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
point_t hit_point
DEPRECATED: Intersection point, use VJOIN1 hit_dist.
Definition: raytrace.h:251
point_t st_max
max X, Y, Z of bounding RPP
Definition: raytrace.h:438
struct hit seg_out
OUT information.
Definition: raytrace.h:371
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
vect_t vol_large
Definition: vol.c:61
#define RT_VOL_INTERNAL_MAGIC
Definition: magic.h:113
fastf_t r_max
exit dist from bounding sphere
Definition: raytrace.h:221
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
#define UNUSED(parameter)
Definition: common.h:239
int nmg_mark_edges_real(const uint32_t *magic_p)
Definition: nmg_misc.c:846
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
void rt_vol_volume(fastf_t *volume, const struct rt_db_internal *ip)
Definition: vol.c:1444
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
Support for uniform tolerances.
Definition: tol.h:71
#define BN_CK_TOL(_p)
Definition: tol.h:82
#define DEBUG_VOL
12 Volume & opaque Binary solid
Definition: raytrace.h:95
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
void bu_vls_struct_print(struct bu_vls *vls, const struct bu_structparse *sdp, const char *base)
struct rt_vol_internal vol_i
Definition: vol.c:55
struct nmgregion * nmg_mrsv(struct model *m)
Definition: nmg_mk.c:306
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
#define NORM_XNEG
Definition: vol.c:92
struct bn_tol rti_tol
Math tolerances for this model.
Definition: raytrace.h:1765
#define bu_offsetof(_t, _m)
Definition: parse.h:64
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
#define RT_GET_SEG(p, res)
Definition: raytrace.h:379
int rt_vol_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: vol.c:637
struct model * nmg_mm(void)
Definition: nmg_mk.c:235
void rt_vol_ifree(struct rt_db_internal *ip)
Definition: vol.c:715
fastf_t r_min
entry dist to bounding sphere
Definition: raytrace.h:220
void rt_vol_centroid(point_t *cent, const struct rt_db_internal *ip)
Definition: vol.c:1302
#define ZERO(val)
Definition: units.c:38
void * idb_ptr
Definition: raytrace.h:195
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
point_t st_min
min X, Y, Z of bounding RPP
Definition: raytrace.h:437
const struct rt_functab OBJ[]
Definition: table.c:159
#define BU_SEM_SYSCALL
Definition: parallel.h:178
int nmg_kill_snakes(struct loopuse *lu)
Definition: nmg_mod.c:3302
void bn_vec_ortho(vect_t out, const vect_t in)
int bu_struct_parse(const struct bu_vls *in_vls, const struct bu_structparse *desc, const char *base, void *data)
Definition: parse.c:878
int rt_vol_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
Definition: vol.c:122
mat_t vol_mat
Definition: vol.c:59
#define RT_CK_SOLTAB(_p)
Definition: raytrace.h:453
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
int rt_vol_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: vol.c:1048
void * st_specific
-> ID-specific (private) struct
Definition: raytrace.h:435
fastf_t crv_c1
curvature in principle dir
Definition: raytrace.h:308
vect_t vol_xnorm
Definition: vol.c:56
Definition: color.c:51
void rt_vol_free(struct soltab *stp)
Definition: vol.c:910
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
int hit_surfno
solid-specific surface indicator
Definition: raytrace.h:255
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
vect_t hit_normal
DEPRECATED: Surface Normal at hit_point, use RT_HIT_NORMAL.
Definition: raytrace.h:252
#define BU_CK_LIST_HEAD(_p)
Definition: list.h:142
#define VOL(_vip, _xx, _yy, _zz)
Definition: vol.c:105
#define BU_CK_EXTERNAL(_p)
Definition: parse.h:224
int rt_vol_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: vol.c:403
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
size_t ext_nbytes
Definition: parse.h:210
void bu_vls_vlscat(struct bu_vls *dest, const struct bu_vls *src)
Definition: vls.c:415
int rt_vol_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: vol.c:503
vect_t vol_origin
Definition: vol.c:60
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
HIDDEN void verbose(struct human_data_t *dude)
Definition: human.c:2008
Definition: vls.h:56
HIDDEN const point_t delta
Definition: sh_prj.c:618
double fastf_t
Definition: defines.h:300
#define VPRINT(a, b)
Definition: raytrace.h:1881
#define VOL_YWIDEN
Definition: vol.c:103
Definition: color.c:50
#define VOL_ZWIDEN
Definition: vol.c:104
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
void nmg_merge_models(struct model *m1, struct model *m2)
Definition: nmg_index.c:738
point_t st_center
Centroid of solid.
Definition: raytrace.h:432
void nmg_region_a(struct nmgregion *r, const struct bn_tol *tol)
Definition: nmg_mk.c:2557