BRL-CAD
dynamic_geometry.c
Go to the documentation of this file.
1 /* D Y N A M I C _ G E O M E T R Y . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2003-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 libwdb/dynamic_geometry.c
21  *
22  * Library for dynamically changing BRL-CAD geometry (i.e., changing
23  * already prepped geometry)
24  *
25  * The typical use of dynamic geometry involves these steps:
26  *
27  * 1. Normal use of " db_dirbuild", "gettrees", and "prep".
28  *
29  * 2. Call "wdb_dbopen" to get a "struct rt_wdb" pointer for the
30  * database (typically using the RT_WDB_TYPE_DB_INMEM flag)
31  *
32  * 3. Create and fill an "rt_reprep_obj_list" structure.
33  *
34  * 4. Call "rt_unprep" and pass it the "rt_reprep_obj_list" structure.
35  *
36  * 5. Modify geometry (note, you may only modify geometry that you
37  * listed in the "rt_reprep_obj_list" as "unprepped"). You may add,
38  * remove, modify, translate, rotate, scale objects under the
39  * "unprepped" combinations. (Use the "make_hole" routine here).
40  *
41  * 6. Call "rt_reprep" with same parameters as you called "rt_unprep".
42  *
43  * 7. If you are using liboptical, call "view_re_setup" to setup
44  * shaders for regions involved.
45  *
46  * 8. Do raytracing.
47  *
48  * If you only need to make holes, a simpler and quicker approach is
49  * to use the "make_hole_in_prepped_regions" routine:
50  *
51  * Steps 1 and 2 are the same as above, then 3. Call "make_hole" and
52  * 4. Do raytracing.
53  */
54 
55 #include "common.h"
56 
57 #include <math.h>
58 #include <string.h>
59 #include "bio.h"
60 
61 #include "vmath.h"
62 #include "bn.h"
63 #include "raytrace.h"
64 #include "wdb.h"
65 
66 
67 int
68 make_hole(struct rt_wdb *wdbp, /* database to be modified */
69  point_t hole_start, /* center of start of hole */
70  vect_t hole_depth, /* depth and direction of hole */
71  fastf_t hole_radius, /* radius of hole */
72  int num_objs, /* number of objects that this hole affects */
73  struct directory **dp) /* array of directory pointers
74  * [num_objs] of objects to
75  * get this hole applied
76  */
77 {
78  struct bu_vls tmp_name = BU_VLS_INIT_ZERO;
79  int i, base_len, count=0;
80 
81  RT_CHECK_WDB(wdbp);
82 
83  /* make sure we are only making holes in combinations, they do not
84  * have to be regions
85  */
86  for (i=0; i<num_objs; i++) {
87  RT_CK_DIR(dp[i]);
88  if (!(dp[i]->d_flags & RT_DIR_COMB)) {
89  bu_log("make_hole(): can only make holes in combinations\n");
90  bu_log("\t%s is not a combination\n", dp[i]->d_namep);
91  return 4;
92  }
93  }
94 
95  /* make a unique name for the RCC we will use (of the form
96  * "make_hole_%d")
97  */
98  bu_vls_strcat(&tmp_name, "make_hole_");
99  base_len = bu_vls_strlen(&tmp_name);
100  bu_vls_strcat(&tmp_name, "0");
101  while ((db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET)) != RT_DIR_NULL) {
102  count++;
103  bu_vls_trunc(&tmp_name, base_len);
104  bu_vls_printf(&tmp_name, "%d", count);
105  }
106 
107  /* build the RCC based on parameters passed in */
108  if (mk_rcc(wdbp, bu_vls_addr(&tmp_name), hole_start, hole_depth, hole_radius)) {
109  bu_log("Failed to create hole cylinder!!!\n");
110  bu_vls_free(&tmp_name);
111  return 2;
112  }
113 
114  /* subtract this RCC from each combination in the list passed in */
115  for (i=0; i<num_objs; i++) {
116  struct rt_db_internal intern;
117  struct rt_comb_internal *comb;
118  union tree *tree;
119 
120  /* get the internal form of the combination */
121  if (rt_db_get_internal(&intern, dp[i], wdbp->dbip, NULL, wdbp->wdb_resp) < 0) {
122  bu_log("Failed to get %s\n", dp[i]->d_namep);
123  bu_vls_free(&tmp_name);
124  return 3;
125  }
126  comb = (struct rt_comb_internal *)intern.idb_ptr;
127 
128  /* Build a new "subtract" node (will be the root of the new tree) */
129  BU_ALLOC(tree, union tree);
130  RT_TREE_INIT(tree);
131  tree->tr_b.tb_op = OP_SUBTRACT;
132  tree->tr_b.tb_left = comb->tree; /* subtract from the original tree */
133  comb->tree = tree;
134 
135  /* Build a node for the RCC to be subtracted */
136  BU_ALLOC(tree, union tree);
137  RT_TREE_INIT(tree);
138  tree->tr_l.tl_op = OP_DB_LEAF;
139  tree->tr_l.tl_mat = NULL;
140  tree->tr_l.tl_name = bu_strdup(bu_vls_addr(&tmp_name)); /* copy name of RCC */
141 
142  /* Put the RCC node to the right of the root */
143  comb->tree->tr_b.tb_right = tree;
144 
145  /* Save the modified combination. This will overwrite the
146  * original combination if wdbp was opened with the
147  * RT_WDB_TYPE_DB_DISK flag. If wdbp was opened with the
148  * RT_WDB_TYPE_DB_INMEM flag, then the combination will be
149  * temporarily over-written in memory only and the disk file
150  * will not be modified.
151  */
152  wdb_put_internal(wdbp, dp[i]->d_namep, &intern, 1.0);
153  }
154  return 0;
155 }
156 
157 
158 int
159 make_hole_in_prepped_regions(struct rt_wdb *wdbp, /* database to be modified */
160  struct rt_i *rtip, /* rt_i pointer for the same database */
161  point_t hole_start, /* center of start of hole */
162  vect_t hole_depth, /* depth and direction of hole */
163  fastf_t radius, /* radius of hole */
164  struct bu_ptbl *regions) /* list of region structures to which this hole
165  * is to be applied
166  */
167 {
168  struct bu_vls tmp_name = BU_VLS_INIT_ZERO;
169  size_t i, base_len, count=0;
170  struct directory *dp;
171  struct rt_db_internal intern;
172  struct soltab *stp;
173 
174  RT_CHECK_WDB(wdbp);
175 
176  /* make a unique name for the RCC we will use (of the form "make_hole_%d") */
177  bu_vls_strcat(&tmp_name, "make_hole_");
178  base_len = bu_vls_strlen(&tmp_name);
179  bu_vls_strcat(&tmp_name, "0");
180  while ((db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET)) != RT_DIR_NULL) {
181  count++;
182  bu_vls_trunc(&tmp_name, base_len);
183  bu_vls_printf(&tmp_name, "%zu", count);
184  }
185 
186  /* build the RCC based on parameters passed in */
187  if (mk_rcc(wdbp, bu_vls_addr(&tmp_name), hole_start, hole_depth, radius)) {
188  bu_log("Failed to create hole cylinder!!!\n");
189  bu_vls_free(&tmp_name);
190  return 2;
191  }
192 
193  /* lookup the newly created RCC */
194  dp=db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET);
195  if (dp == RT_DIR_NULL) {
196  bu_log("Failed to lookup RCC (%s) just made by make_hole_in_prepped_regions()!!!\n",
197  bu_vls_addr(&tmp_name));
198  bu_bomb("Failed to lookup RCC just made by make_hole_in_prepped_regions()!!!\n");
199  }
200 
201  /* get the internal form of the new RCC */
202  if (rt_db_get_internal(&intern, dp, wdbp->dbip, NULL, wdbp->wdb_resp) < 0) {
203  bu_log("Failed to get internal form of RCC (%s) just made by make_hole_in_prepped_regions()!!!\n",
204  bu_vls_addr(&tmp_name));
205  bu_bomb("Failed to get internal form of RCC just made by make_hole_in_prepped_regions()!!!\n");
206  }
207 
208  /* Build a soltab structure for the new RCC */
209  BU_ALLOC(stp, struct soltab);
210  stp->l.magic = RT_SOLTAB_MAGIC;
211  stp->l2.magic = RT_SOLTAB2_MAGIC;
212  stp->st_uses = 1;
213  stp->st_dp = dp;
214  stp->st_bit = rtip->nsolids++;
215 
216  /* Add the new soltab structure to the rt_i structure */
217  rtip->rti_Solids = (struct soltab **)bu_realloc(rtip->rti_Solids,
218  rtip->nsolids * sizeof(struct soltab *),
219  "new rti_Solids");
220  rtip->rti_Solids[stp->st_bit] = stp;
221 
222  /* actually prep the new RCC */
223  if (intern.idb_meth->ft_prep(stp, &intern, rtip)) {
224  bu_log("Failed to prep RCC (%s) just made by make_hole_in_prepped_regions()!!!\n",
225  bu_vls_addr(&tmp_name));
226  bu_bomb("Failed to prep RCC just made by make_hole_in_prepped_regions()!!!\n");
227  }
228 
229  /* initialize the soltabs list of containing regions */
230  bu_ptbl_init(&stp->st_regions, BU_PTBL_LEN(regions), "stp->st_regions");
231 
232  /* Subtract the new RCC from each region structure in the list provided */
233  for (i=0; i<BU_PTBL_LEN(regions); i++) {
234  struct region *rp;
235  union tree *treep;
236 
237  /* get the next region structure */
238  rp = (struct region *)BU_PTBL_GET(regions, i);
239 
240  RT_CK_REGION(rp);
241 
242  /* create a tree node for the subtraction operation, this will be the new tree root */
243  BU_ALLOC(treep, union tree);
244  RT_TREE_INIT(treep);
245  treep->tr_b.tb_op = OP_SUBTRACT;
246  treep->tr_b.tb_left = rp->reg_treetop; /* subtract from the old treetop */
247  treep->tr_b.tb_regionp = rp;
248 
249  /* make the new node the new treetop */
250  rp->reg_treetop = treep;
251 
252  /* create a tree node for the new RCC */
253  BU_ALLOC(treep, union tree);
254  RT_TREE_INIT(treep);
255  treep->tr_a.tu_op = OP_SOLID;
256  treep->tr_a.tu_stp = stp;
257  treep->tr_a.tu_regionp = rp;
258 
259  /* the new RCC gets hung on the right of the subtract node */
260  rp->reg_treetop->tr_b.tb_right = treep;
261 
262  /* make sure the "all unions" flag is not set on this region */
263  rp->reg_all_unions = 0;
264 
265  /* Add this region to the list of containing regions for the new RCC */
266  bu_ptbl_ins(&stp->st_regions, (long *)rp);
267  }
268 
269  /* insert the new RCC soltab structure into the already existing space partitioning tree */
270  insert_in_bsp(stp, &rtip->rti_CutHead);
271 
272  return 0;
273 }
274 
275 
276 /*
277  * Local Variables:
278  * mode: C
279  * tab-width: 8
280  * indent-tabs-mode: t
281  * c-file-style: "stroustrup"
282  * End:
283  * ex: shiftwidth=4 tabstop=8
284  */
int mk_rcc(struct rt_wdb *fp, const char *name, const point_t base, const vect_t height, fastf_t radius)
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
int rt_db_get_internal(struct rt_db_internal *ip, const struct directory *dp, const struct db_i *dbip, const mat_t mat, struct resource *resp)
Definition: dir.c:76
const struct directory * st_dp
Directory entry of solid.
Definition: raytrace.h:436
int tb_op
non-leaf
Definition: raytrace.h:1147
struct db_i * dbip
Definition: raytrace.h:1266
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
#define RT_SOLTAB2_MAGIC
Definition: magic.h:168
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
short reg_all_unions
1=boolean tree is all unions
Definition: raytrace.h:551
#define RT_CHECK_WDB(_p)
Definition: raytrace.h:1291
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
int tu_op
leaf, OP_SOLID
Definition: raytrace.h:1154
struct region * tb_regionp
ptr to containing region
Definition: raytrace.h:1148
void insert_in_bsp(struct soltab *stp, union cutter *cutp)
Definition: cut.c:2198
int make_hole(struct rt_wdb *wdbp, point_t hole_start, vect_t hole_depth, fastf_t hole_radius, int num_objs, struct directory **dp)
Header file for the BRL-CAD common definitions.
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
#define RT_CK_REGION(_p)
Definition: raytrace.h:559
struct bu_list l
links, headed by rti_headsolid
Definition: raytrace.h:426
#define RT_TREE_INIT(_p)
Definition: raytrace.h:1189
int wdb_put_internal(struct rt_wdb *wdbp, const char *name, struct rt_db_internal *ip, double local2mm)
Definition: wdb.c:218
union tree * tb_left
Definition: raytrace.h:1149
struct soltab * tu_stp
Definition: raytrace.h:1156
Definition: ptbl.h:62
long st_bit
solids bit vector index (const)
Definition: raytrace.h:439
struct region * tu_regionp
ptr to containing region
Definition: raytrace.h:1155
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
#define OP_SUBTRACT
Binary: L subtract R.
Definition: raytrace.h:1129
#define OP_DB_LEAF
Leaf of combination, db fmt.
Definition: raytrace.h:1139
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define RT_CK_DIR(_dp)
Definition: raytrace.h:876
union cutter rti_CutHead
Head of cut tree.
Definition: raytrace.h:1793
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#define LOOKUP_QUIET
Definition: raytrace.h:893
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
int(* ft_prep)(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: raytrace.h:2047
matp_t tl_mat
xform matp, NULL ==> identity
Definition: raytrace.h:1173
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
struct tree::tree_node tr_b
#define RT_SOLTAB_MAGIC
Definition: magic.h:169
void * bu_realloc(void *ptr, size_t siz, const char *str)
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
uint32_t magic
Magic # for mem id/check.
Definition: list.h:119
struct soltab ** rti_Solids
ptrs to soltab [st_bit]
Definition: raytrace.h:1809
struct bu_ptbl st_regions
ptrs to regions using this solid (const)
Definition: raytrace.h:440
#define BU_PTBL_LEN(ptbl)
Definition: ptbl.h:107
struct tree::tree_db_leaf tr_l
union tree * tb_right
Definition: raytrace.h:1150
void * idb_ptr
Definition: raytrace.h:195
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
size_t nsolids
total # of solids participating
Definition: raytrace.h:1783
struct bu_list l2
links, headed by st_dp->d_use_hd
Definition: raytrace.h:427
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define RT_DIR_NULL
Definition: raytrace.h:875
union tree * reg_treetop
Pointer to boolean tree.
Definition: raytrace.h:540
int make_hole_in_prepped_regions(struct rt_wdb *wdbp, struct rt_i *rtip, point_t hole_start, vect_t hole_depth, fastf_t radius, struct bu_ptbl *regions)
struct resource * wdb_resp
Definition: raytrace.h:1270
long st_uses
Usage count, for instanced solids.
Definition: raytrace.h:430
#define OP_SOLID
Leaf: tr_stp -> solid.
Definition: raytrace.h:1126
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
int tl_op
leaf, OP_DB_LEAF
Definition: raytrace.h:1172
Definition: vls.h:56
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
struct tree::tree_leaf tr_a
#define bu_strdup(s)
Definition: str.h:71