BRL-CAD
xpush.c
Go to the documentation of this file.
1 /* X P U S H . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-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 libged/xpush.c
21  *
22  * The xpush command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <string.h>
29 
30 #include "bu/cmd.h"
31 
32 #include "./ged_private.h"
33 
34 
35 struct object_use
36 {
37  struct bu_list l;
38  struct directory *dp;
39  mat_t xform;
40  int used;
41 };
42 
43 
44 static void
45 increment_uses(struct db_i *UNUSED(db_ip), struct directory *dp, void *UNUSED(ptr))
46 {
47  RT_CK_DIR(dp);
48 
49  dp->d_uses++;
50 }
51 
52 
53 static void
54 increment_nrefs(struct db_i *UNUSED(db_ip), struct directory *dp, void *UNUSED(ptr))
55 {
56  RT_CK_DIR(dp);
57 
58  dp->d_nref++;
59 }
60 
61 
62 static void
63 Free_uses(struct db_i *dbip)
64 {
65  int i;
66 
67  for (i = 0; i <RT_DBNHASH; i++) {
68  struct directory *dp;
69  struct object_use *use;
70 
71  for (dp = dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
72  if (!(dp->d_flags & (RT_DIR_SOLID | RT_DIR_COMB)))
73  continue;
74 
75  while (BU_LIST_NON_EMPTY(&dp->d_use_hd)) {
76  use = BU_LIST_FIRST(object_use, &dp->d_use_hd);
77  if (!use->used) {
78  if (use->dp->d_un.file_offset >= 0) {
79  /* was written to disk */
80  if (db_delete(dbip, use->dp) != 0)
81  bu_log("Free_uses: db_delete failure!\n");
82  }
83  if (db_dirdelete(dbip, use->dp) < 0) {
84  bu_log("Free_uses: db_dirdelete failure!\n");
85  }
86  }
87  BU_LIST_DEQUEUE(&use->l);
88  bu_free((void *)use, "Free_uses: use");
89  }
90 
91  }
92  }
93 
94 }
95 
96 
97 static void
98 Make_new_name(struct db_i *dbip,
99  struct directory *dp,
100  void *ptr)
101 {
102  struct object_use *use;
103  int use_no;
104  int digits;
105  int suffix_start;
106  int name_length;
107  int j;
108  char format_v4[50], format_v5[50];
109  struct bu_vls name_v5 = BU_VLS_INIT_ZERO;
110  char name_v4[NAMESIZE+1];
111  char *name;
112  struct ged *gedp;
113 
114  /* only one use and not referenced elsewhere, nothing to do */
115  if (dp->d_uses < 2 && dp->d_uses == dp->d_nref)
116  return;
117 
118  /* check if already done */
119  if (BU_LIST_NON_EMPTY(&dp->d_use_hd))
120  return;
121 
122  gedp = (struct ged *)ptr;
123 
124  digits = log10((double)dp->d_uses) + 2.0;
125  snprintf(format_v5, 50, "%%s_%%0%dd", digits);
126  snprintf(format_v4, 50, "_%%0%dd", digits);
127 
128  name_length = (int)strlen(dp->d_namep);
129  if (name_length + digits + 1 > NAMESIZE - 1)
130  suffix_start = NAMESIZE - digits - 2;
131  else
132  suffix_start = name_length;
133 
134  j = 0;
135  for (use_no=0; use_no<dp->d_uses; use_no++) {
136  j++;
137  BU_ALLOC(use, struct object_use);
138 
139  /* set xform for this object_use to all zeros */
140  MAT_ZERO(use->xform);
141  use->used = 0;
142  if (db_version(dbip) < 5) {
143  NAMEMOVE(dp->d_namep, name_v4);
144  name_v4[NAMESIZE] = '\0'; /* ensure null termination */
145  }
146 
147  /* Add an entry for the original at the end of the list
148  * This insures that the original will be last to be modified
149  * If original were modified earlier, copies would be screwed-up
150  */
151  if (use_no == dp->d_uses-1 && dp->d_uses == dp->d_nref)
152  use->dp = dp;
153  else {
154  if (db_version(dbip) < 5) {
155  snprintf(&name_v4[suffix_start], NAMESIZE-suffix_start, format_v4, j);
156  name = name_v4;
157  } else {
158  bu_vls_trunc(&name_v5, 0);
159  bu_vls_printf(&name_v5, format_v5, dp->d_namep, j);
160  name = bu_vls_addr(&name_v5);
161  }
162 
163  /* Insure that new name is unique */
164  while (db_lookup(dbip, name, 0) != RT_DIR_NULL) {
165  j++;
166  if (db_version(dbip) < 5) {
167  snprintf(&name_v4[suffix_start], NAMESIZE-suffix_start, format_v4, j);
168  name = name_v4;
169  } else {
170  bu_vls_trunc(&name_v5, 0);
171  bu_vls_printf(&name_v5, format_v5, dp->d_namep, j);
172  name = bu_vls_addr(&name_v5);
173  }
174  }
175 
176  /* Add new name to directory */
177  use->dp = db_diradd(dbip, name, RT_DIR_PHONY_ADDR, 0, dp->d_flags, (void *)&dp->d_minor_type);
178  if (use->dp == RT_DIR_NULL) {
179  bu_vls_printf(gedp->ged_result_str, "\nAn error has occurred while adding a new object to the database.\n"); \
180  return;
181  }
182  }
183 
184  /* Add new directory pointer to use list for this object */
185  BU_LIST_INSERT(&dp->d_use_hd, &use->l);
186  }
187 
188  bu_vls_free(&name_v5);
189 }
190 
191 
192 /* Do_copy_membs() needs the forward declaration due to a cyclic dependency */
193 static struct directory *Copy_object(struct ged *gedp, struct directory *dp, mat_t xform);
194 
195 static void
196 Do_copy_membs(struct db_i *dbip, struct rt_comb_internal *UNUSED(comb), union tree *comb_leaf, void *user_ptr1, void *user_ptr2, void *UNUSED(user_ptr3), void *UNUSED(user_ptr4))
197 {
198  struct directory *dp;
199  struct directory *dp_new;
200  mat_t new_xform;
201  matp_t xform;
202  struct ged *gedp;
203 
204  RT_CK_DBI(dbip);
205  RT_CK_TREE(comb_leaf);
206 
207  if ((dp = db_lookup(dbip, comb_leaf->tr_l.tl_name, LOOKUP_QUIET)) == RT_DIR_NULL)
208  return;
209 
210  xform = (matp_t)user_ptr1;
211  gedp = (struct ged *)user_ptr2;
212 
213  /* apply transform matrix for this arc */
214  if (comb_leaf->tr_l.tl_mat) {
215  bn_mat_mul(new_xform, xform, comb_leaf->tr_l.tl_mat);
216  } else {
217  MAT_COPY(new_xform, xform);
218  }
219 
220  /* Copy member with current transform matrix */
221  if ((dp_new=Copy_object(gedp, dp, new_xform)) == RT_DIR_NULL) {
222  bu_vls_printf(gedp->ged_result_str, "Failed to copy object %s", dp->d_namep);
223  return;
224  }
225 
226  /* replace member name with new copy */
227  bu_free(comb_leaf->tr_l.tl_name, "comb_leaf->tr_l.tl_name");
228  comb_leaf->tr_l.tl_name = bu_strdup(dp_new->d_namep);
229 
230  /* make transform for this arc the identity matrix */
231  if (!comb_leaf->tr_l.tl_mat) {
232  comb_leaf->tr_l.tl_mat = (matp_t)bu_malloc(sizeof(mat_t), "tl_mat");
233  }
234  MAT_IDN(comb_leaf->tr_l.tl_mat);
235 }
236 
237 
238 static struct directory *
239 Copy_solid(struct ged *gedp,
240  struct directory *dp,
241  mat_t xform)
242 {
243  struct directory *found;
244  struct rt_db_internal sol_int;
245  struct object_use *use;
246 
247  RT_CK_DIR(dp);
248 
249  if (!(dp->d_flags & RT_DIR_SOLID)) {
250  bu_vls_printf(gedp->ged_result_str, "Copy_solid: %s is not a solid!!!!\n", dp->d_namep);
251  return RT_DIR_NULL;
252  }
253 
254  /* If no transformation is to be applied, just use the original */
255  if (bn_mat_is_identity(xform)) {
256  /* find original in the list */
257  for (BU_LIST_FOR (use, object_use, &dp->d_use_hd)) {
258  if (use->dp == dp && use->used == 0) {
259  use->used = 1;
260  return dp;
261  }
262  }
263  }
264 
265  /* Look for a copy that already has this transform matrix */
266  for (BU_LIST_FOR (use, object_use, &dp->d_use_hd)) {
267  if (bn_mat_is_equal(xform, use->xform, &gedp->ged_wdbp->wdb_tol)) {
268  /* found a match, no need to make another copy */
269  use->used = 1;
270  return use->dp;
271  }
272  }
273 
274  /* get a fresh use */
275  found = RT_DIR_NULL;
276  for (BU_LIST_FOR (use, object_use, &dp->d_use_hd)) {
277  if (use->used)
278  continue;
279 
280  found = use->dp;
281  use->used = 1;
282  MAT_COPY(use->xform, xform);
283  break;
284  }
285 
286  if (found == RT_DIR_NULL && dp->d_nref == 1 && dp->d_uses == 1) {
287  /* only one use, take it */
288  found = dp;
289  }
290 
291  if (found == RT_DIR_NULL) {
292  bu_vls_printf(gedp->ged_result_str, "Ran out of uses for solid %s\n", dp->d_namep);
293  return RT_DIR_NULL;
294  }
295 
296  if (rt_db_get_internal(&sol_int, dp, gedp->ged_wdbp->dbip, xform, &rt_uniresource) < 0) {
297  bu_vls_printf(gedp->ged_result_str, "Cannot import solid %s\n", dp->d_namep);
298  return RT_DIR_NULL;
299  }
300 
301  RT_CK_DB_INTERNAL(&sol_int);
302  if (rt_db_put_internal(found, gedp->ged_wdbp->dbip, &sol_int, &rt_uniresource) < 0) {
303  bu_vls_printf(gedp->ged_result_str, "Cannot write copy solid (%s) to database\n", found->d_namep);
304  return RT_DIR_NULL;
305  }
306 
307  return found;
308 }
309 
310 
311 static struct directory *
312 Copy_comb(struct ged *gedp,
313  struct directory *dp,
314  mat_t xform)
315 {
316  struct object_use *use;
317  struct directory *found;
318  struct rt_db_internal intern;
319  struct rt_comb_internal *comb;
320 
321  RT_CK_DIR(dp);
322 
323  /* Look for a copy that already has this transform matrix */
324  for (BU_LIST_FOR (use, object_use, &dp->d_use_hd)) {
325  if (bn_mat_is_equal(xform, use->xform, &gedp->ged_wdbp->wdb_tol)) {
326  /* found a match, no need to make another copy */
327  use->used = 1;
328  return use->dp;
329  }
330  }
331 
332  /* if we can't get records for this combination, just leave it alone */
333  if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0)
334  return dp;
335  comb = (struct rt_comb_internal *)intern.idb_ptr;
336 
337  /* copy members */
338  if (comb->tree)
339  db_tree_funcleaf(gedp->ged_wdbp->dbip, comb, comb->tree, Do_copy_membs,
340  (void *)xform, (void *)gedp, (void *)0, (void *)NULL);
341 
342  /* Get a use of this object */
343  found = RT_DIR_NULL;
344  for (BU_LIST_FOR (use, object_use, &dp->d_use_hd)) {
345  /* Get a fresh use of this object */
346  if (use->used)
347  continue; /* already used */
348  found = use->dp;
349  use->used = 1;
350  MAT_COPY(use->xform, xform);
351  break;
352  }
353 
354  if (found == RT_DIR_NULL && dp->d_nref == 1 && dp->d_uses == 1) {
355  /* only one use, so take original */
356  found = dp;
357  }
358 
359  if (found == RT_DIR_NULL) {
360  bu_vls_printf(gedp->ged_result_str, "Ran out of uses for combination %s\n", dp->d_namep);
361  return RT_DIR_NULL;
362  }
363 
364  if (rt_db_put_internal(found, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) {
365  bu_vls_printf(gedp->ged_result_str, "rt_db_put_internal failed for %s\n", dp->d_namep);
366  rt_db_free_internal(&intern);
367  return RT_DIR_NULL;
368  }
369 
370  return found;
371 }
372 
373 
374 static struct directory *
375 Copy_object(struct ged *gedp,
376  struct directory *dp,
377  mat_t xform)
378 {
379  RT_CK_DIR(dp);
380 
381  if (dp->d_flags & RT_DIR_SOLID)
382  return Copy_solid(gedp, dp, xform);
383  else
384  return Copy_comb(gedp, dp, xform);
385 }
386 
387 
388 static void
389 Do_ref_incr(struct db_i *dbip, struct rt_comb_internal *UNUSED(comb), union tree *comb_leaf, void *UNUSED(user_ptr1), void *UNUSED(user_ptr2), void *UNUSED(user_ptr3), void *UNUSED(user_ptr4))
390 {
391  struct directory *dp;
392 
393  RT_CK_DBI(dbip);
394  RT_CK_TREE(comb_leaf);
395 
396  if ((dp = db_lookup(dbip, comb_leaf->tr_l.tl_name, LOOKUP_QUIET)) == RT_DIR_NULL)
397  return;
398 
399  dp->d_nref++;
400 }
401 
402 
403 static struct directory *Copy_object(struct ged *gedp, struct directory *dp, fastf_t *xform);
404 
405 static void Do_ref_incr(struct db_i *dbip, struct rt_comb_internal *comb, union tree *comb_leaf, void *user_ptr1, void *user_ptr2, void *user_ptr3, void *UNUSED(user_ptr4));
406 
407 
408 int
409 ged_xpush(struct ged *gedp, int argc, const char *argv[])
410 {
411  struct directory *old_dp;
412  struct rt_db_internal intern;
413  struct rt_comb_internal *comb;
414  struct bu_ptbl tops;
415  mat_t xform;
416  int i;
417  static const char *usage = "object";
418 
421  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
422 
423  /* initialize result */
424  bu_vls_trunc(gedp->ged_result_str, 0);
425 
426  /* must be wanting help */
427  if (argc == 1) {
428  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
429  return GED_HELP;
430  }
431 
432  if (argc != 2) {
433  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
434  return GED_ERROR;
435  }
436 
437  /* get directory pointer for arg */
438  if ((old_dp = db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_NOISY)) == RT_DIR_NULL)
439  return GED_ERROR;
440 
441  if (old_dp->d_flags & RT_DIR_SOLID) {
442  bu_log("Attempt to xpush a primitive, aborting.\n");
443  return GED_ERROR;
444  }
445 
446  /* Initialize use and reference counts of all directory entries */
447  for (i = 0; i < RT_DBNHASH; i++) {
448  struct directory *dp;
449 
450  for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
451  if (!(dp->d_flags & (RT_DIR_SOLID | RT_DIR_COMB)))
452  continue;
453 
454  dp->d_uses = 0;
455  dp->d_nref = 0;
456  }
457  }
458 
459  /* Count uses in the tree being pushed (updates dp->d_uses) */
460  db_functree(gedp->ged_wdbp->dbip, old_dp, increment_uses, increment_uses, &rt_uniresource, NULL);
461 
462  /* Do a simple reference count to find top level objects */
463  for (i = 0; i < RT_DBNHASH; i++) {
464  struct directory *dp;
465 
466  for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
467  if (dp->d_flags & RT_DIR_SOLID)
468  continue;
469 
470  if (!(dp->d_flags & (RT_DIR_SOLID | RT_DIR_COMB)))
471  continue;
472 
473  if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
474  bu_vls_printf(gedp->ged_result_str, "Database read error, aborting.\n");
475  return GED_ERROR;
476  }
477  comb = (struct rt_comb_internal *)intern.idb_ptr;
478  if (comb->tree)
479  db_tree_funcleaf(gedp->ged_wdbp->dbip, comb, comb->tree, Do_ref_incr,
480  (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL);
481  rt_db_free_internal(&intern);
482  }
483  }
484 
485  /* anything with zero references is a tree top */
486  bu_ptbl_init(&tops, 0, "tops for xpush");
487  for (i = 0; i < RT_DBNHASH; i++) {
488  struct directory *dp;
489 
490  for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
491  if (dp->d_flags & RT_DIR_SOLID)
492  continue;
493 
494  if (!(dp->d_flags & (RT_DIR_SOLID | RT_DIR_COMB)))
495  continue;
496 
497  if (dp->d_nref == 0)
498  bu_ptbl_ins(&tops, (long *)dp);
499  }
500  }
501 
502  /* now re-zero the reference counts */
503  for (i = 0; i < RT_DBNHASH; i++) {
504  struct directory *dp;
505 
506  for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
507  if (!(dp->d_flags & (RT_DIR_SOLID | RT_DIR_COMB)))
508  continue;
509 
510  dp->d_nref = 0;
511  }
512  }
513 
514  /* accurately count references in entire model */
515  for (i = 0; i < BU_PTBL_END(&tops); i++) {
516  struct directory *dp;
517 
518  dp = (struct directory *)BU_PTBL_GET(&tops, i);
519  db_functree(gedp->ged_wdbp->dbip, dp, increment_nrefs, increment_nrefs, &rt_uniresource, NULL);
520  }
521 
522  /* Free list of tree-tops */
523  bu_ptbl_free(&tops);
524 
525  /* Make new names */
526  db_functree(gedp->ged_wdbp->dbip, old_dp, Make_new_name, Make_new_name, &rt_uniresource, (void *)gedp);
527 
528  MAT_IDN(xform);
529 
530  /* Make new objects */
531  if (rt_db_get_internal(&intern, old_dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
532  bu_vls_printf(gedp->ged_result_str, "ERROR: cannot load %s feom the database!!!\n", old_dp->d_namep);
533  bu_vls_printf(gedp->ged_result_str, "\tNothing has been changed!!\n");
534  Free_uses(gedp->ged_wdbp->dbip);
535  return GED_ERROR;
536  }
537 
538  comb = (struct rt_comb_internal *)intern.idb_ptr;
539  if (!comb->tree) {
540  Free_uses(gedp->ged_wdbp->dbip);
541  return GED_OK;
542  }
543 
544  db_tree_funcleaf(gedp->ged_wdbp->dbip, comb, comb->tree, Do_copy_membs,
545  (void *)xform, (void *)gedp, (void *)0, (void *)NULL);
546 
547  if (rt_db_put_internal(old_dp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) {
548  bu_vls_printf(gedp->ged_result_str, "rt_db_put_internal failed for %s\n", old_dp->d_namep);
549  rt_db_free_internal(&intern);
550  Free_uses(gedp->ged_wdbp->dbip);
551  return GED_ERROR;
552  }
553 
554  /* Free use lists and delete unused directory entries */
555  Free_uses(gedp->ged_wdbp->dbip);
556  return GED_OK;
557 }
558 
559 
560 /*
561  * Local Variables:
562  * tab-width: 8
563  * mode: C
564  * indent-tabs-mode: t
565  * c-file-style: "stroustrup"
566  * End:
567  * ex: shiftwidth=4 tabstop=8
568  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
char * d_namep
pointer to name string
Definition: raytrace.h:859
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
Definition: raytrace.h:800
int db_dirdelete(struct db_i *, struct directory *dp)
Definition: db_lookup.c:262
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
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
#define RT_DBNHASH
hash table is an array of linked lists with this many array pointer elements (Memory use for 32-bit: ...
Definition: raytrace.h:755
int bn_mat_is_identity(const mat_t m)
Definition: mat.c:980
Definition: list.h:118
int rt_db_put_internal(struct directory *dp, struct db_i *dbip, struct rt_db_internal *ip, struct resource *resp)
Definition: dir.c:136
long d_nref
times ref'ed by COMBs
Definition: raytrace.h:868
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
Definition: clone.c:90
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
long d_uses
uses, from instancing
Definition: raytrace.h:866
off_t file_offset
disk address in obj file
Definition: raytrace.h:861
int db_version(struct db_i *dbip)
Definition: db5_scan.c:414
int ged_xpush(struct ged *gedp, int argc, const char *argv[])
Definition: xpush.c:409
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
mat_t xform
Definition: xpush.c:39
struct directory * d_forw
link to next dir entry
Definition: raytrace.h:864
#define BU_LIST_NON_EMPTY(hp)
Definition: list.h:296
#define GED_ERROR
Definition: ged.h:61
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
Definition: ptbl.h:62
if(share_geom)
Definition: nmg_mod.c:3829
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
unsigned char d_minor_type
object minor type
Definition: raytrace.h:871
int bn_mat_is_equal(const mat_t a, const mat_t b, const struct bn_tol *tol)
Definition: mat.c:925
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define RT_CK_DIR(_dp)
Definition: raytrace.h:876
#define RT_DIR_SOLID
this name is a solid
Definition: raytrace.h:883
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#define LOOKUP_QUIET
Definition: raytrace.h:893
matp_t tl_mat
xform matp, NULL ==> identity
Definition: raytrace.h:1173
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
#define UNUSED(parameter)
Definition: common.h:239
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
struct bu_list d_use_hd
heads list of uses (struct soltab l2)
Definition: raytrace.h:872
struct bu_list l
Definition: xpush.c:37
int used
Definition: xpush.c:40
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
union directory::@8 d_un
struct directory * db_diradd(struct db_i *, const char *name, off_t laddr, size_t len, int flags, void *ptr)
Definition: db_lookup.c:190
struct tree::tree_db_leaf tr_l
void * idb_ptr
Definition: raytrace.h:195
struct bn_tol wdb_tol
Definition: raytrace.h:1269
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
struct directory * dbi_Head[RT_DBNHASH]
Definition: raytrace.h:814
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
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
#define LOOKUP_NOISY
Definition: raytrace.h:892
void * ptr
ptr to in-memory-only obj
Definition: raytrace.h:862
#define GED_HELP
Definition: ged.h:62
void db_functree(struct db_i *dbip, struct directory *dp, void(*comb_func)(struct db_i *, struct directory *, void *), void(*leaf_func)(struct db_i *, struct directory *, void *), struct resource *resp, void *client_data)
Definition: db_walk.c:199
void db_tree_funcleaf(struct db_i *dbip, struct rt_comb_internal *comb, union tree *comb_tree, void(*leaf_func)(struct db_i *, struct rt_comb_internal *, union tree *, void *, void *, void *, void *), void *user_ptr1, void *user_ptr2, void *user_ptr3, void *user_ptr4)
Definition: db_tree.c:640
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define RT_CK_TREE(_p)
Definition: raytrace.h:1182
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int d_flags
flags
Definition: raytrace.h:869
Definition: vls.h:56
double fastf_t
Definition: defines.h:300
int db_delete(struct db_i *, struct directory *dp)
Definition: db_alloc.c:132
struct directory * dp
Definition: xpush.c:38
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
#define bu_strdup(s)
Definition: str.h:71