BRL-CAD
db_comb.c
Go to the documentation of this file.
1 /* D B _ C O M B . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1996-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 db4 */
21 /** @{ */
22 /** @file db_comb.c
23  *
24  * This module contains the import/export routines for "Combinations",
25  * the non-leaf nodes in the directed acyclic graphs (DAGs) in the
26  * BRL-CAD ".g" database.
27  *
28  * This parallels the function of the geometry (leaf-node)
29  * import/export routines found in the g_xxx.c routines.
30  *
31  * As a reminder, some combinations are special, when marked with the
32  * "Region" flag, everything from that node down is considered to be
33  * made of uniform material.
34  *
35  */
36 
37 #include "common.h"
38 
39 #include <limits.h>
40 #include <math.h>
41 #include <string.h>
42 #include "bio.h"
43 
44 
45 #include "vmath.h"
46 #include "bn.h"
47 #include "db.h"
48 #include "mater.h"
49 #include "raytrace.h"
50 
51 #include "../librt_private.h"
52 
53 
54 #define STAT_ROT 1
55 #define STAT_XLATE 2
56 #define STAT_PERSP 4
57 #define STAT_SCALE 8
58 
59 
60 /**
61  * Describe with a bit vector the effects this matrix will have.
62  */
63 static int
64 db_comb_mat_categorize(const fastf_t *matp)
65 {
66  int status = 0;
67 
68  if (!matp) return 0;
69 
70  if (!ZERO(matp[0] - 1.0)
71  || !ZERO(matp[5] - 1.0)
72  || !ZERO(matp[10] - 1.0))
73  {
74  status |= STAT_ROT;
75  }
76 
77  if (!ZERO(matp[MDX])
78  || !ZERO(matp[MDY])
79  || !ZERO(matp[MDZ]))
80  {
81  status |= STAT_XLATE;
82  }
83 
84  if (!ZERO(matp[12])
85  || !ZERO(matp[13])
86  || !ZERO(matp[14]))
87  {
88  status |= STAT_PERSP;
89  }
90 
91  if (!ZERO(matp[15]))
92  status |= STAT_SCALE;
93 
94  return status;
95 }
96 
97 
98 size_t
99 db_tree_nleaves(const union tree *tp)
100 {
101  if (tp == TREE_NULL) return 0;
102 
103  RT_CK_TREE(tp);
104 
105  switch (tp->tr_op) {
106  case OP_NOP:
107  return 0;
108  case OP_DB_LEAF:
109  return 1;
110  case OP_SOLID:
111  return 1;
112  case OP_REGION:
113  return 1;
114 
115  case OP_NOT:
116  case OP_GUARD:
117  case OP_XNOP:
118  /* Unary ops */
119  return db_tree_nleaves(tp->tr_b.tb_left);
120 
121  case OP_UNION:
122  case OP_INTERSECT:
123  case OP_SUBTRACT:
124  case OP_XOR:
125  /* This node is known to be a binary op */
126  return db_tree_nleaves(tp->tr_b.tb_left) +
128 
129  default:
130  bu_log("db_tree_nleaves: bad op %d\n", tp->tr_op);
131  bu_bomb("db_tree_nleaves\n");
132  }
133  return 0; /* for the compiler */
134 }
135 
136 
137 struct rt_tree_array *
140  union tree *tp,
141  int op,
142  int freeflag,
143  struct resource *resp)
144 {
145 
146  RT_CK_TREE(tp);
147  RT_CK_RESOURCE(resp);
148 
149  switch (tp->tr_op) {
150  case OP_DB_LEAF:
151  rt_tree_array->tl_op = op;
152  rt_tree_array->tl_tree = tp;
153  return rt_tree_array+1;
154 
155  case OP_UNION:
156  case OP_INTERSECT:
157  case OP_SUBTRACT:
158  /* This node is known to be a binary op */
159  rt_tree_array = db_flatten_tree(rt_tree_array, tp->tr_b.tb_left, op, freeflag, resp);
160  rt_tree_array = db_flatten_tree(rt_tree_array, tp->tr_b.tb_right, tp->tr_op, freeflag, resp);
161  if (freeflag) {
162  /* The leaves have been stolen, free the binary op */
163  tp->tr_b.tb_left = TREE_NULL;
164  tp->tr_b.tb_right = TREE_NULL;
165  RT_FREE_TREE(tp, resp);
166  }
167  return rt_tree_array;
168 
169  default:
170  bu_log("db_flatten_tree: bad op %d\n", tp->tr_op);
171  bu_bomb("db_flatten_tree\n");
172  }
173 
174  return (struct rt_tree_array *)NULL; /* for the compiler */
175 }
176 
177 
178 int
180  struct rt_db_internal *ip,
181  const struct bu_external *ep,
182  const mat_t matrix, /* NULL if identity */
183  const struct db_i *dbip,
184  struct resource *resp)
185 {
186  union record *rp;
188  union tree *tree;
189  struct rt_comb_internal *comb;
190  size_t j;
191  size_t node_count;
192 
193  BU_CK_EXTERNAL(ep);
194  rp = (union record *)ep->ext_buf;
195  if (dbip) RT_CK_DBI(dbip);
196 
197  if (rp[0].u_id != ID_COMB) {
198  bu_log("rt_comb_import4: Attempt to import a non-combination\n");
199  return -1;
200  }
201 
202  /* Compute how many granules of MEMBER records follow */
203  node_count = ep->ext_nbytes/sizeof(union record) - 1;
204 
205  if (node_count)
206  rt_tree_array = (struct rt_tree_array *)bu_calloc(node_count, sizeof(struct rt_tree_array), "rt_tree_array");
207  else
208  rt_tree_array = (struct rt_tree_array *)NULL;
209 
210  for (j = 0; j < node_count; j++) {
211  if (rp[j+1].u_id != ID_MEMB) {
212  bu_free((void *)rt_tree_array, "rt_comb_import4: rt_tree_array");
213  bu_log("rt_comb_import4(): granule in external buffer is not ID_MEMB, id=%d\n", rp[j+1].u_id);
214  return -1;
215  }
216 
217  switch (rp[j+1].M.m_relation) {
218  case DB_OP_INTERSECT:
219  rt_tree_array[j].tl_op = OP_INTERSECT;
220  break;
221  case DB_OP_SUBTRACT:
222  rt_tree_array[j].tl_op = OP_SUBTRACT;
223  break;
224  default:
225  bu_log("rt_comb_import4() unknown op=x%x, assuming UNION\n", rp[j+1].M.m_relation);
226  /* Fall through */
227  case DB_OP_UNION:
228  rt_tree_array[j].tl_op = OP_UNION;
229  break;
230  }
231 
232  /* Build leaf node for in-memory tree */
233  {
234  union tree *tp;
235  mat_t diskmat;
236  char namebuf[NAMESIZE+1];
237 
238  RT_GET_TREE(tp, resp);
239  rt_tree_array[j].tl_tree = tp;
240  tp->tr_l.tl_op = OP_DB_LEAF;
241 
242  /* bu_strlcpy not safe here, buffer size mismatch */
243  memset(namebuf, 0, NAMESIZE+1);
244  memcpy(namebuf, rp[j+1].M.m_instname, sizeof(rp[j+1].M.m_instname));
245 
246  tp->tr_l.tl_name = bu_strdup(namebuf);
247 
248  flip_mat_dbmat(diskmat, rp[j+1].M.m_mat, dbip->dbi_version < 0 ? 1 : 0);
249 
250  /* Verify that rotation part is pure rotation */
251  if (fabs(diskmat[0]) > 1 || fabs(diskmat[1]) > 1 ||
252  fabs(diskmat[2]) > 1 ||
253  fabs(diskmat[4]) > 1 || fabs(diskmat[5]) > 1 ||
254  fabs(diskmat[6]) > 1 ||
255  fabs(diskmat[8]) > 1 || fabs(diskmat[9]) > 1 ||
256  fabs(diskmat[10]) > 1)
257  {
258  bu_log("ERROR: %s/%s improper scaling, rotation matrix elements > 1\n",
259  rp[0].c.c_name, namebuf);
260  }
261 
262  /* Verify that perspective isn't used as a modeling transform */
263  if (!ZERO(diskmat[12])
264  || !ZERO(diskmat[13])
265  || !ZERO(diskmat[14]))
266  {
267  bu_log("ERROR: %s/%s has perspective transform\n", rp[0].c.c_name, namebuf);
268  }
269 
270  /* See if disk record is identity matrix */
271  if (bn_mat_is_identity(diskmat)) {
272  if (matrix == NULL) {
273  tp->tr_l.tl_mat = NULL; /* identity */
274  } else {
275  tp->tr_l.tl_mat = bn_mat_dup(matrix);
276  }
277  } else {
278  if (matrix == NULL) {
279  tp->tr_l.tl_mat = bn_mat_dup(diskmat);
280  } else {
281  mat_t prod;
282  bn_mat_mul(prod, matrix, diskmat);
283  tp->tr_l.tl_mat = bn_mat_dup(prod);
284  }
285  }
286 /* bu_log("M_name=%s, matp=x%x\n", tp->tr_l.tl_name, tp->tr_l.tl_mat); */
287  }
288  }
289  if (node_count)
290  tree = db_mkgift_tree(rt_tree_array, node_count, &rt_uniresource);
291  else
292  tree = (union tree *)NULL;
293 
295  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
296  ip->idb_type = ID_COMBINATION;
297  ip->idb_meth = &OBJ[ID_COMBINATION];
298 
299  BU_ALLOC(comb, struct rt_comb_internal);
300  RT_COMB_INTERNAL_INIT(comb);
301 
302  comb->tree = tree;
303 
304  ip->idb_ptr = (void *)comb;
305 
306  switch (rp[0].c.c_flags) {
307  case DBV4_NON_REGION_NULL:
308  case DBV4_NON_REGION:
309  comb->region_flag = 0;
310  break;
311  case DBV4_REGION:
312  comb->region_flag = 1;
314  break;
315  case DBV4_REGION_FASTGEN_PLATE:
316  comb->region_flag = 1;
318  break;
319  case DBV4_REGION_FASTGEN_VOLUME:
320  comb->region_flag = 1;
322  break;
323  default:
324  bu_log("WARNING: combination %s has illegal c_flag=x%x\n",
325  rp[0].c.c_name, rp[0].c.c_flags);
326  break;
327  }
328 
329  if (comb->region_flag) {
330  if (dbip->dbi_version < 0) {
331  comb->region_id = flip_short(rp[0].c.c_regionid);
332  comb->aircode = flip_short(rp[0].c.c_aircode);
333  comb->GIFTmater = flip_short(rp[0].c.c_material);
334  comb->los = flip_short(rp[0].c.c_los);
335  } else {
336  comb->region_id = rp[0].c.c_regionid;
337  comb->aircode = rp[0].c.c_aircode;
338  comb->GIFTmater = rp[0].c.c_material;
339  comb->los = rp[0].c.c_los;
340  }
341  } else {
342  /* set some reasonable defaults */
343  comb->region_id = 0;
344  comb->aircode = 0;
345  comb->GIFTmater = 0;
346  comb->los = 0;
347  }
348 
349  comb->rgb_valid = rp[0].c.c_override;
350  if (comb->rgb_valid) {
351  comb->rgb[0] = rp[0].c.c_rgb[0];
352  comb->rgb[1] = rp[0].c.c_rgb[1];
353  comb->rgb[2] = rp[0].c.c_rgb[2];
354  }
355  if (rp[0].c.c_matname[0] != '\0') {
356 #define MAX_SS 128
357  char shader_str[MAX_SS];
358 
359  memset(shader_str, 0, MAX_SS);
360 
361  /* copy shader info to a static string */
362 
363  /* write shader name. c_matname is a buffer, bu_strlcpy not
364  * safe here.
365  */
366  memcpy(shader_str, rp[0].c.c_matname, sizeof(rp[0].c.c_matname));
367 
368  bu_strlcat(shader_str, " ", MAX_SS);
369 
370  /* write shader parameters. c_matparm is a buffer, bu_strlcpy
371  * not safe here.
372  */
373  memcpy(shader_str+strlen(shader_str), rp[0].c.c_matparm, sizeof(rp[0].c.c_matparm));
374 
375  /* convert to TCL format and place into comb->shader */
376  if (bu_shader_to_list(shader_str, &comb->shader)) {
377  bu_log("rt_comb_import4: Error: Cannot convert following shader to TCL format:\n");
378  bu_log("\t%s\n", shader_str);
379  bu_vls_free(&comb->shader);
380  return -1;
381  }
382  }
383  /* XXX Separate flags for color inherit, shader inherit, (new) material inherit? */
384  /* XXX cf: ma_cinherit, ma_minherit */
385  /* This ? is necessary to clean up old databases with grunge here */
386  comb->inherit = (rp[0].c.c_inherit == DB_INH_HIGHER) ? 1 : 0;
387  /* Automatic material table lookup here? */
388  if (comb->region_flag)
389  bu_vls_printf(&comb->material, "gift%ld", comb->GIFTmater);
390 
391  if (rt_tree_array) bu_free((void *)rt_tree_array, "rt_tree_array");
392 
393  return 0;
394 }
395 
396 
397 int
399  struct bu_external *ep,
400  const struct rt_db_internal *ip,
401  double UNUSED(local2mm),
402  const struct db_i *dbip,
403  struct resource *resp)
404 {
405  struct rt_comb_internal *comb;
406  size_t node_count;
407  size_t actual_count;
409  union tree *tp;
410  union record *rp;
411  size_t j;
412  char *endp;
413  struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
414 
415  RT_CK_DB_INTERNAL(ip);
416  if (dbip) RT_CK_DBI(dbip);
417  RT_CK_RESOURCE(resp);
418  if (ip->idb_type != ID_COMBINATION) bu_bomb("rt_comb_export4() type not ID_COMBINATION");
419  comb = (struct rt_comb_internal *)ip->idb_ptr;
420  RT_CK_COMB(comb);
421 
422  if (comb->tree && db_ck_v4gift_tree(comb->tree) < 0) {
423  db_non_union_push(comb->tree, resp);
424  if (db_ck_v4gift_tree(comb->tree) < 0) {
425  /* Need to further modify tree */
426  bu_log("rt_comb_export4() Unable to V4-ify tree, aborting.\n");
427  rt_pr_tree(comb->tree, 0);
428  return -1;
429  }
430  }
431 
432  /* Count # leaves in tree -- that's how many Member records needed. */
433  node_count = db_tree_nleaves(comb->tree);
434  if (node_count > 0) {
435  rt_tree_array = (struct rt_tree_array *)bu_calloc(node_count, sizeof(struct rt_tree_array), "rt_tree_array");
436 
437  /* Convert tree into array form */
438  actual_count = db_flatten_tree(rt_tree_array, comb->tree,
439  OP_UNION, 1, resp) - rt_tree_array;
440  BU_ASSERT_SIZE_T(actual_count, ==, node_count);
441  comb->tree = TREE_NULL;
442  } else {
443  rt_tree_array = (struct rt_tree_array *)NULL;
444  actual_count = 0;
445  }
446 
447  /* Reformat the data into the necessary V4 granules */
448  BU_EXTERNAL_INIT(ep);
449  ep->ext_nbytes = sizeof(union record) * (1 + node_count);
450  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "v4 comb external");
451  rp = (union record *)ep->ext_buf;
452 
453  /* Convert the member records */
454  for (j = 0; j < node_count; j++) {
455  tp = rt_tree_array[j].tl_tree;
456  RT_CK_TREE(tp);
457  if (tp->tr_op != OP_DB_LEAF) bu_bomb("rt_comb_export4() tree not OP_DB_LEAF");
458 
459  rp[j+1].u_id = ID_MEMB;
460  switch (rt_tree_array[j].tl_op) {
461  case OP_INTERSECT:
462  rp[j+1].M.m_relation = DB_OP_INTERSECT;
463  break;
464  case OP_SUBTRACT:
465  rp[j+1].M.m_relation = DB_OP_SUBTRACT;
466  break;
467  case OP_UNION:
468  rp[j+1].M.m_relation = DB_OP_UNION;
469  break;
470  default:
471  bu_bomb("rt_comb_export4() corrupt rt_tree_array");
472  }
473 
474  NAMEMOVE(tp->tr_l.tl_name, rp[j+1].M.m_instname);
475  rp[j+1].M.m_instname[NAMESIZE-1] = '\0'; /* sanity */
476 
477  if (tp->tr_l.tl_mat) {
478  flip_dbmat_mat(rp[j+1].M.m_mat, tp->tr_l.tl_mat);
479  } else {
480  flip_dbmat_mat(rp[j+1].M.m_mat, bn_mat_identity);
481  }
482  db_free_tree(tp, resp);
483  }
484 
485  /* Build the Combination record, on the front */
486  rp[0].u_id = ID_COMB;
487  /* c_name[] filled in by db_wrap_v4_external() */
488  if (comb->region_flag) {
489  rp[0].c.c_regionid = (short)comb->region_id;
490  rp[0].c.c_aircode = (short)comb->aircode;
491  rp[0].c.c_material = (short)comb->GIFTmater;
492  rp[0].c.c_los = (short)comb->los;
493  switch (comb->is_fastgen) {
495  rp[0].c.c_flags = DBV4_REGION_FASTGEN_PLATE;
496  break;
498  rp[0].c.c_flags = DBV4_REGION_FASTGEN_VOLUME;
499  break;
500  default:
501  case REGION_NON_FASTGEN:
502  rp[0].c.c_flags = DBV4_REGION;
503  break;
504  }
505  } else {
506  rp[0].c.c_flags = DBV4_NON_REGION;
507  }
508  if (comb->rgb_valid) {
509  rp[0].c.c_override = 1;
510  rp[0].c.c_rgb[0] = comb->rgb[0];
511  rp[0].c.c_rgb[1] = comb->rgb[1];
512  rp[0].c.c_rgb[2] = comb->rgb[2];
513  }
514 
515  /* convert TCL list format shader to keyword=value format */
516  if (bu_shader_to_key_eq(bu_vls_addr(&comb->shader), &tmp_vls)) {
517 
518  bu_log("rt_comb_export4: Cannot convert following shader string to keyword=value format:\n");
519  bu_log("\t%s\n", bu_vls_addr(&comb->shader));
520  rp[0].c.c_matparm[0] = '\0';
521  rp[0].c.c_matname[0] = '\0';
522  return -1;
523  } else {
524  endp = strchr(bu_vls_addr(&tmp_vls), ' ');
525  if (endp) {
526  size_t len;
527  len = endp - bu_vls_addr(&tmp_vls);
528  if (len <= 0 && bu_vls_strlen(&tmp_vls) > 0) {
529  bu_log("WARNING: leading spaces on shader '%s' implies NULL shader\n",
530  bu_vls_addr(&tmp_vls));
531  }
532 
533  if (len >= sizeof(rp[0].c.c_matname)) {
534  bu_log("ERROR: Shader name '%s' exceeds v4 database field, aborting.\n",
535  bu_vls_addr(&tmp_vls));
536  return -1;
537  }
538  if (strlen(endp+1) >= sizeof(rp[0].c.c_matparm)) {
539  bu_log("ERROR: Shader parameters '%s' exceed database field, aborting.\nUse \"dbupgrade\" to enable unlimited length strings.\n",
540  endp+1);
541  return -1;
542  }
543 
544  /* stash as string even though c_matname/parm are NAMESIZE buffers */
545  bu_strlcpy(rp[0].c.c_matname, bu_vls_addr(&tmp_vls), sizeof(rp[0].c.c_matname));
546  bu_strlcpy(rp[0].c.c_matparm, endp+1, sizeof(rp[0].c.c_matparm));
547  } else {
548  if ((size_t)bu_vls_strlen(&tmp_vls) >= sizeof(rp[0].c.c_matname)) {
549  bu_log("ERROR: Shader name '%s' exceeds v4 database field, aborting.\n",
550  bu_vls_addr(&tmp_vls));
551  return -1;
552  }
553  bu_strlcpy(rp[0].c.c_matname, bu_vls_addr(&tmp_vls), sizeof(rp[0].c.c_matname));
554  rp[0].c.c_matparm[0] = '\0';
555  }
556  }
557  bu_vls_free(&tmp_vls);
558 
559  rp[0].c.c_inherit = comb->inherit;
560 
561  if (rt_tree_array) bu_free((char *)rt_tree_array, "rt_tree_array");
562 
563  return 0; /* OK */
564 }
565 
566 
567 void
569  struct bu_vls *vls,
570  const union tree *tp,
571  int indented,
572  int lvl,
573  double mm2local,
574  struct resource *resp)
575 {
576  size_t i;
577  size_t node_count;
579  char op = OP_NOP;
580  int status;
581  union tree *ntp;
582 
583  BU_CK_VLS(vls);
584  RT_CK_RESOURCE(resp);
585 
586  if (!tp) {
587  /* no tree, probably an empty combination */
588  bu_vls_strcat(vls, "-empty-\n");
589  return;
590  }
591  RT_CK_TREE(tp);
592 
593  node_count = db_tree_nleaves(tp);
594  if (node_count == 0) {
595  if (!indented) bu_vls_spaces(vls, 2*lvl);
596  bu_vls_strcat(vls, "-empty-\n");
597  return;
598  }
599 
600  /*
601  * We're going to whack the heck out of the tree, but our
602  * argument is 'const'. Before getting started, make a
603  * private copy just for us.
604  */
605  ntp = db_dup_subtree(tp, resp);
606  RT_CK_TREE(ntp);
607 
608  /* Convert to "v4 / GIFT style", so that the flatten makes sense. */
609  if (db_ck_v4gift_tree(ntp) < 0)
610  db_non_union_push(ntp, resp);
611  RT_CK_TREE(ntp);
612 
613  node_count = db_tree_nleaves(ntp);
614  rt_tree_array = (struct rt_tree_array *)bu_calloc(node_count, sizeof(struct rt_tree_array), "rt_tree_array");
615 
616  /*
617  * free=0 means that the tree won't have any leaf nodes freed.
618  */
619  (void)db_flatten_tree(rt_tree_array, ntp, OP_UNION, 0, resp);
620 
621  for (i=0; i<node_count; i++) {
622  union tree *itp = rt_tree_array[i].tl_tree;
623 
624  RT_CK_TREE(itp);
625  BU_ASSERT_LONG(itp->tr_op, ==, OP_DB_LEAF);
626  BU_ASSERT_PTR(itp->tr_l.tl_name, !=, NULL);
627 
628  switch (rt_tree_array[i].tl_op) {
629  case OP_INTERSECT:
630  op = DB_OP_INTERSECT;
631  break;
632  case OP_SUBTRACT:
633  op = DB_OP_SUBTRACT;
634  break;
635  case OP_UNION:
636  op = DB_OP_UNION;
637  break;
638  default:
639  bu_bomb("db_tree_flatten_describe() corrupt rt_tree_array");
640  }
641 
642  status = db_comb_mat_categorize(itp->tr_l.tl_mat);
643  if (!indented) bu_vls_spaces(vls, 2*lvl);
644  bu_vls_printf(vls, " %c %s", op, itp->tr_l.tl_name);
645  if (status & STAT_ROT) {
646  fastf_t az, el;
647  bn_ae_vec(&az, &el, itp->tr_l.tl_mat ?
648  itp->tr_l.tl_mat : bn_mat_identity);
649  bu_vls_printf(vls,
650  " az=%g, el=%g, ",
651  az, el);
652  }
653  if (status & STAT_XLATE) {
654  bu_vls_printf(vls, " [%g, %g, %g]",
655  itp->tr_l.tl_mat[MDX]*mm2local,
656  itp->tr_l.tl_mat[MDY]*mm2local,
657  itp->tr_l.tl_mat[MDZ]*mm2local);
658  }
659  if (status & STAT_SCALE) {
660  bu_vls_printf(vls, " scale %g",
661  1.0/itp->tr_l.tl_mat[15]);
662  }
663  if (status & STAT_PERSP) {
664  bu_vls_printf(vls,
665  " Perspective=[%g, %g, %g]??",
666  itp->tr_l.tl_mat[12],
667  itp->tr_l.tl_mat[13],
668  itp->tr_l.tl_mat[14]);
669  }
670  bu_vls_printf(vls, "\n");
671  }
672 
673  if (rt_tree_array) bu_free((void *)rt_tree_array, "rt_tree_array");
674  db_free_tree(ntp, resp);
675 }
676 
677 
678 void
680  struct bu_vls *vls,
681  const union tree *tp,
682  int indented,
683  int lvl,
684  double mm2local)
685 {
686  int status;
687 
688  BU_CK_VLS(vls);
689 
690  if (!tp) {
691  /* no tree, probably an empty combination */
692  bu_vls_strcat(vls, "-empty-\n");
693  return;
694  }
695  RT_CK_TREE(tp);
696  switch (tp->tr_op) {
697 
698  case OP_DB_LEAF:
699  status = db_comb_mat_categorize(tp->tr_l.tl_mat);
700 
701  /* One per line, out onto the vls */
702  if (!indented) bu_vls_spaces(vls, 2*lvl);
703  bu_vls_strcat(vls, tp->tr_l.tl_name);
704  if (status & STAT_ROT) {
705  fastf_t az, el;
706  bn_ae_vec(&az, &el, tp->tr_l.tl_mat ?
707  tp->tr_l.tl_mat : bn_mat_identity);
708  bu_vls_printf(vls,
709  " az=%g, el=%g, ",
710  az, el);
711  }
712  if (status & STAT_XLATE) {
713  bu_vls_printf(vls, " [%g, %g, %g]",
714  tp->tr_l.tl_mat[MDX]*mm2local,
715  tp->tr_l.tl_mat[MDY]*mm2local,
716  tp->tr_l.tl_mat[MDZ]*mm2local);
717  }
718  if (status & STAT_SCALE) {
719  bu_vls_printf(vls, " scale %g",
720  1.0/tp->tr_l.tl_mat[15]);
721  }
722  if (status & STAT_PERSP) {
723  bu_vls_printf(vls,
724  " Perspective=[%g, %g, %g]??",
725  tp->tr_l.tl_mat[12],
726  tp->tr_l.tl_mat[13],
727  tp->tr_l.tl_mat[14]);
728  }
729  bu_vls_printf(vls, "\n");
730  return;
731 
732  /* This node is known to be a binary op */
733  case OP_UNION:
734  if (!indented) bu_vls_spaces(vls, 2*lvl);
735  bu_vls_printf(vls, "%c ", DB_OP_UNION);
736  goto bin;
737  case OP_INTERSECT:
738  if (!indented) bu_vls_spaces(vls, 2*lvl);
739  bu_vls_printf(vls, "%c ", DB_OP_INTERSECT);
740  goto bin;
741  case OP_SUBTRACT:
742  if (!indented) bu_vls_spaces(vls, 2*lvl);
743  bu_vls_printf(vls, "%c ", DB_OP_SUBTRACT);
744  goto bin;
745  case OP_XOR:
746  if (!indented) bu_vls_spaces(vls, 2*lvl);
747  bu_vls_strcat(vls, "^ ");
748  bin:
749  db_tree_describe(vls, tp->tr_b.tb_left, 1, lvl+1, mm2local);
750  db_tree_describe(vls, tp->tr_b.tb_right, 0, lvl+1, mm2local);
751  return;
752 
753  /* This node is known to be a unary op */
754  case OP_NOT:
755  if (!indented) bu_vls_spaces(vls, 2*lvl);
756  bu_vls_strcat(vls, "! ");
757  goto unary;
758  case OP_GUARD:
759  if (!indented) bu_vls_spaces(vls, 2*lvl);
760  bu_vls_strcat(vls, "G ");
761  goto unary;
762  case OP_XNOP:
763  if (!indented) bu_vls_spaces(vls, 2*lvl);
764  bu_vls_strcat(vls, "X ");
765  unary:
766  db_tree_describe(vls, tp->tr_b.tb_left, 1, lvl+1, mm2local);
767  return;
768 
769  case OP_NOP:
770  if (!indented) bu_vls_spaces(vls, 2*lvl);
771  bu_vls_strcat(vls, "NOP\n");
772  return;
773 
774  default:
775  bu_log("db_tree_describe: bad op %d\n", tp->tr_op);
776  bu_bomb("db_tree_describe\n");
777  }
778 }
779 
780 
781 void
783  struct bu_vls *str,
784  const struct rt_comb_internal *comb,
785  int verbose,
786  double mm2local,
787  struct resource *resp)
788 {
789  RT_CK_COMB(comb);
790  RT_CK_RESOURCE(resp);
791 
792  if (comb->region_flag) {
793  bu_vls_printf(str,
794  "REGION id=%ld (air=%ld, los=%ld, GIFTmater=%ld) ",
795  comb->region_id,
796  comb->aircode,
797  comb->los,
798  comb->GIFTmater);
799 
800  if (comb->is_fastgen == REGION_FASTGEN_PLATE)
801  bu_vls_printf(str, "(FASTGEN plate mode) ");
802  else if (comb->is_fastgen == REGION_FASTGEN_VOLUME)
803  bu_vls_printf(str, "(FASTGEN volume mode) ");
804  }
805 
806  bu_vls_strcat(str, "--\n");
807  if (bu_vls_strlen(&comb->shader) > 0) {
808  bu_vls_printf(str,
809  "Shader '%s'\n",
810  bu_vls_addr(&comb->shader));
811  }
812 
813  if (comb->rgb_valid) {
814  bu_vls_printf(str,
815  "Color %d %d %d\n",
816  comb->rgb[0],
817  comb->rgb[1],
818  comb->rgb[2]);
819  }
820 
821  if (bu_vls_strlen(&comb->shader) > 0 || comb->rgb_valid) {
822  if (comb->inherit) {
823  bu_vls_strcat(str,
824  "(These material properties override all lower ones in the tree)\n");
825  }
826  }
827 
828  if (comb->tree) {
829  if (verbose) {
830  db_tree_flatten_describe(str, comb->tree, 0, 1, mm2local, resp);
831  } else {
832  rt_pr_tree_vls(str, comb->tree);
833  }
834  } else {
835  bu_vls_strcat(str, "(empty tree)\n");
836  }
837 }
838 
839 
840 /**
841  * Free the storage associated with the rt_db_internal version of this combination.
842  */
843 void
845 {
846  register struct rt_comb_internal *comb;
847 
848  RT_CK_DB_INTERNAL(ip);
849  comb = (struct rt_comb_internal *)ip->idb_ptr;
850 
851  if (comb) {
852  /* If tree hasn't been stolen, release it */
854  RT_FREE_COMB_INTERNAL(comb);
855  bu_free((void *)comb, "comb ifree");
856  }
857  ip->idb_ptr = ((void *)0); /* sanity */
858 }
859 
860 
861 int
863  struct bu_vls *str,
864  const struct rt_db_internal *ip,
865  int verbose,
866  double mm2local,
867  struct resource *resp,
868  struct db_i *dbip)
869 {
870  const struct rt_comb_internal *comb;
871 
872  RT_CK_DB_INTERNAL(ip);
873  RT_CK_RESOURCE(resp);
874  if (dbip) RT_CK_DBI(dbip);
875 
876  comb = (struct rt_comb_internal *)ip->idb_ptr;
877  RT_CK_COMB(comb);
878 
879  db_comb_describe(str, comb, verbose, mm2local, resp);
880  return 0;
881 }
882 
883 
884 void
885 db_wrap_v4_external(struct bu_external *op, const char *name)
886 {
887  union record *rec;
888 
889  BU_CK_EXTERNAL(op);
890 
891  rec = (union record *)op->ext_buf;
892  NAMEMOVE(name, rec->s.s_name);
893  rec->s.s_name[NAMESIZE-1] = '\0';
894 }
895 
896 
897 int
899  const union tree *tp,
900  int no_unions)
901 {
902  RT_CK_TREE(tp);
903  switch (tp->tr_op) {
904 
905  case OP_DB_LEAF:
906  break;
907 
908  case OP_UNION:
909  if (no_unions) return -1;
910  /* else fall through */
911  case OP_INTERSECT:
912  case OP_SUBTRACT:
913  case OP_XOR:
914  if (db_ck_left_heavy_tree(tp->tr_b.tb_right, no_unions) < 0)
915  return -1;
916  return db_ck_left_heavy_tree(tp->tr_b.tb_left, no_unions);
917 
918  default:
919  bu_log("db_ck_left_heavy_tree: bad op %d\n", tp->tr_op);
920  bu_bomb("db_ck_left_heavy_tree\n");
921  }
922  return 0;
923 }
924 
925 
926 int
927 db_ck_v4gift_tree(const union tree *tp)
928 {
929  RT_CK_TREE(tp);
930  switch (tp->tr_op) {
931 
932  case OP_DB_LEAF:
933  break;
934 
935  case OP_UNION:
936  if (db_ck_v4gift_tree(tp->tr_b.tb_left) < 0)
937  return -1;
938  return db_ck_v4gift_tree(tp->tr_b.tb_right);
939 
940  case OP_INTERSECT:
941  case OP_SUBTRACT:
942  case OP_XOR:
943  return db_ck_left_heavy_tree(tp, 1);
944 
945  default:
946  bu_log("db_ck_v4gift_tree: bad op %d\n", tp->tr_op);
947  bu_bomb("db_ck_v4gift_tree\n");
948  }
949  return 0;
950 }
951 
952 
953 union tree *
956  size_t howfar,
957  struct resource *resp)
958 {
959  register struct rt_tree_array *tlp;
960  size_t i;
961  register struct rt_tree_array *first_tlp = (struct rt_tree_array *)0;
962  register union tree *xtp;
963  register union tree *curtree;
964  register int inuse;
965 
966  RT_CK_RESOURCE(resp);
967 
968  if (howfar == 0)
969  return TREE_NULL;
970 
971  /* Count number of non-null sub-trees to do */
972  for (i = howfar, inuse = 0, tlp = rt_tree_array; i > 0; i--, tlp++) {
973  if (tlp->tl_tree == TREE_NULL)
974  continue;
975  if (inuse++ == 0)
976  first_tlp = tlp;
977  }
978 
979  /* Handle trivial cases */
980  if (inuse <= 0)
981  return TREE_NULL;
982  if (inuse == 1) {
983  curtree = first_tlp->tl_tree;
984  first_tlp->tl_tree = TREE_NULL;
985  return curtree;
986  }
987 
988  if (first_tlp->tl_op != OP_UNION) {
989  first_tlp->tl_op = OP_UNION; /* Fix it */
990  if (RT_G_DEBUG & DEBUG_TREEWALK) {
991  bu_log("db_mkbool_tree() WARNING: non-union (%c) first operation ignored\n",
992  first_tlp->tl_op);
993  }
994  }
995 
996  curtree = first_tlp->tl_tree;
997  first_tlp->tl_tree = TREE_NULL;
998  tlp=first_tlp+1;
999  for (i=howfar-(tlp-rt_tree_array); i>0; i--, tlp++) {
1000  if (tlp->tl_tree == TREE_NULL)
1001  continue;
1002 
1003  RT_GET_TREE(xtp, resp);
1004  xtp->tr_b.tb_left = curtree;
1005  xtp->tr_b.tb_right = tlp->tl_tree;
1006  xtp->tr_b.tb_regionp = (struct region *)0;
1007  xtp->tr_op = tlp->tl_op;
1008  curtree = xtp;
1009  tlp->tl_tree = TREE_NULL; /* empty the input slot */
1010  }
1011  return curtree;
1012 }
1013 
1014 
1015 union tree *
1016 db_mkgift_tree(struct rt_tree_array *trees, size_t subtreecount, struct resource *resp)
1017 {
1018  struct rt_tree_array *tstart;
1019  struct rt_tree_array *tnext;
1020  union tree *curtree;
1021  long i;
1022  long j;
1023  long treecount;
1024 
1025  RT_CK_RESOURCE(resp);
1026 
1027  BU_ASSERT_SIZE_T(subtreecount, <, LONG_MAX);
1028  treecount = (long)subtreecount;
1029 
1030  /*
1031  * This is how GIFT interpreted equations, so it is duplicated here.
1032  * Any expressions between UNIONs are evaluated first. For example:
1033  * A - B - C u D - E - F
1034  * becomes (A - B - C) u (D - E - F)
1035  * so first do the parenthesised parts, and then go
1036  * back and glue the unions together.
1037  * As always, unions are the downfall of free enterprise!
1038  */
1039  tstart = trees;
1040  tnext = trees+1;
1041  for (i=treecount-1; i>=0; i--, tnext++) {
1042  /* If we went off end, or hit a union, do it */
1043 
1044  if (i>0 && tnext->tl_op != OP_UNION)
1045  continue;
1046 
1047  j = tnext-tstart;
1048  if (j <= 0)
1049  continue;
1050 
1051  curtree = db_mkbool_tree(tstart, (size_t)j, resp);
1052  /* db_mkbool_tree() has side effect of zapping tree array,
1053  * so build new first node in array.
1054  */
1055  tstart->tl_op = OP_UNION;
1056  tstart->tl_tree = curtree;
1057 
1058  if (RT_G_DEBUG&DEBUG_TREEWALK) {
1059  bu_log("db_mkgift_tree() intermediate term:\n");
1060  rt_pr_tree(tstart->tl_tree, 0);
1061  }
1062 
1063  /* tstart here at union */
1064  tstart = tnext;
1065  }
1066 
1067  curtree = db_mkbool_tree(trees, subtreecount, resp);
1068  if (RT_G_DEBUG&DEBUG_TREEWALK) {
1069  bu_log("db_mkgift_tree() returns:\n");
1070  rt_pr_tree(curtree, 0);
1071  }
1072  return curtree;
1073 }
1074 
1075 
1076 int
1077 rt_comb_get_color(unsigned char rgb[3], const struct rt_comb_internal *comb)
1078 {
1079  struct mater *mp = MATER_NULL;
1080 
1081  if (!comb)
1082  return 0;
1083 
1084  RT_CK_COMB(comb);
1085 
1086  if (comb->rgb_valid) {
1087  rgb[0] = comb->rgb[0];
1088  rgb[1] = comb->rgb[1];
1089  rgb[2] = comb->rgb[2];
1090  return 1;
1091  }
1092 
1093  for (mp = rt_material_head(); mp != MATER_NULL; mp = mp->mt_forw) {
1094  if (comb->region_id <= mp->mt_high && comb->region_id >= mp->mt_low) {
1095  rgb[0] = mp->mt_r;
1096  rgb[1] = mp->mt_g;
1097  rgb[2] = mp->mt_b;
1098  return 1;
1099  }
1100  }
1101 
1102  /* fail */
1103  return 0;
1104 }
1105 
1106 int
1107 db_comb_mvall(struct directory *dp, struct db_i *dbip, const char *old_name, const char *new_name, struct bu_ptbl *stack)
1108 {
1109  struct rt_db_internal intern;
1110  struct rt_comb_internal *comb;
1111  union tree *comb_leaf;
1112  int done=0;
1113  int changed=0;
1114 
1115  /* Make sure the stack bu_ptbl is ready */
1116  bu_ptbl_reset(stack);
1117 
1118  if (!(dp->d_flags & RT_DIR_COMB)) return 0;
1119 
1120  if (rt_db_get_internal(&intern, dp, dbip, (fastf_t *)NULL, &rt_uniresource) < 0) return 0;
1121 
1122  comb = (struct rt_comb_internal *)intern.idb_ptr;
1123  comb_leaf = comb->tree;
1124 
1125  if (comb_leaf) {
1126  while (!done) {
1127  while (comb_leaf->tr_op != OP_DB_LEAF) {
1128  bu_ptbl_ins(stack, (long *)comb_leaf);
1129  comb_leaf = comb_leaf->tr_b.tb_left;
1130  }
1131 
1132  if (BU_STR_EQUAL(comb_leaf->tr_l.tl_name, old_name)) {
1133  bu_free(comb_leaf->tr_l.tl_name, "comb_leaf->tr_l.tl_name");
1134  comb_leaf->tr_l.tl_name = bu_strdup(new_name);
1135  changed = 1;
1136  }
1137 
1138  if (BU_PTBL_END(stack) < 1) {
1139  done = 1;
1140  break;
1141  }
1142  comb_leaf = (union tree *)BU_PTBL_GET(stack, BU_PTBL_END(stack)-1);
1143  if (comb_leaf->tr_op != OP_DB_LEAF) {
1144  bu_ptbl_rm(stack, (long *)comb_leaf);
1145  comb_leaf = comb_leaf->tr_b.tb_right;
1146  }
1147  }
1148  }
1149 
1150  if (changed) {
1151  if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource)) {
1152  rt_db_free_internal(&intern);
1153  return 2;
1154  }
1155  }
1156 
1157  rt_db_free_internal(&intern);
1158 
1159  /* success */
1160  return 1;
1161 }
1162 
1163 /** @} */
1164 /*
1165  * Local Variables:
1166  * mode: C
1167  * tab-width: 8
1168  * indent-tabs-mode: t
1169  * c-file-style: "stroustrup"
1170  * End:
1171  * ex: shiftwidth=4 tabstop=8
1172  */
void bn_ae_vec(fastf_t *azp, fastf_t *elp, const vect_t v)
Definition: mat.c:374
void db_tree_flatten_describe(struct bu_vls *vls, const union tree *tp, int indented, int lvl, double mm2local, struct resource *resp)
Definition: db_comb.c:568
Definition: raytrace.h:800
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
int bn_mat_is_identity(const mat_t m)
Definition: mat.c:980
int bu_shader_to_list(const char *in, struct bu_vls *vls)
Definition: parse.c:1933
char region_flag
!0 ==> this COMB is a REGION
Definition: raytrace.h:939
int rt_comb_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local, struct resource *resp, struct db_i *dbip)
Definition: db_comb.c:862
#define REGION_FASTGEN_PLATE
Definition: raytrace.h:554
int rt_db_put_internal(struct directory *dp, struct db_i *dbip, struct rt_db_internal *ip, struct resource *resp)
Definition: dir.c:136
struct rt_tree_array * db_flatten_tree(struct rt_tree_array *rt_tree_array, union tree *tp, int op, int freeflag, struct resource *resp)
Definition: db_comb.c:138
#define OP_NOP
Leaf with no effect.
Definition: raytrace.h:1132
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
Definition: clone.c:90
void db_comb_describe(struct bu_vls *str, const struct rt_comb_internal *comb, int verbose, double mm2local, struct resource *resp)
Definition: db_comb.c:782
int rt_comb_get_color(unsigned char rgb[3], const struct rt_comb_internal *comb)
Definition: db_comb.c:1077
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
#define OP_XOR
Binary: L xor R, not both.
Definition: raytrace.h:1130
#define MAX_SS
#define BU_ASSERT_LONG(_lhs, _relation, _rhs)
Definition: defines.h:240
int rt_comb_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip, struct resource *resp)
Definition: db_comb.c:398
#define RT_CK_COMB(_p)
Definition: raytrace.h:955
struct region * tb_regionp
ptr to containing region
Definition: raytrace.h:1148
int bu_ptbl_rm(struct bu_ptbl *b, const long *p)
union tree * tl_tree
Definition: raytrace.h:1247
union tree * db_mkgift_tree(struct rt_tree_array *trees, size_t subtreecount, struct resource *resp)
Definition: db_comb.c:1016
Header file for the BRL-CAD common definitions.
void flip_dbmat_mat(dbfloat_t *dbp, const fastf_t *ff)
Definition: db_flip.c:166
#define OP_XNOP
Unary: L, mark region.
Definition: raytrace.h:1136
void rt_pr_tree_vls(struct bu_vls *vls, const union tree *tp)
unsigned char rgb[3]
Definition: raytrace.h:948
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
#define ID_COMBINATION
Combination Record.
Definition: raytrace.h:499
void bu_ptbl_reset(struct bu_ptbl *b)
Definition: ptbl.c:49
void rt_pr_tree(const union tree *tp, int lvl)
void flip_mat_dbmat(fastf_t *ff, const dbfloat_t *dbp, int flip)
Definition: db_flip.c:107
union tree * tb_left
Definition: raytrace.h:1149
#define STAT_PERSP
Definition: db_comb.c:56
Definition: ptbl.h:62
if(share_geom)
Definition: nmg_mod.c:3829
char * strchr(const char *sp, int c)
int idb_major_type
Definition: raytrace.h:192
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
#define OP_SUBTRACT
Binary: L subtract R.
Definition: raytrace.h:1129
void db_non_union_push(union tree *tp, struct resource *resp)
Definition: db_tree.c:1426
#define BU_CK_VLS(_vp)
Definition: vls.h:69
void * memset(void *s, int c, size_t n)
#define RT_FREE_TREE(_tp, _res)
Definition: raytrace.h:1232
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define OP_INTERSECT
Binary: L intersect R.
Definition: raytrace.h:1128
#define RT_G_DEBUG
Definition: raytrace.h:1718
size_t db_tree_nleaves(const union tree *tp)
Definition: db_comb.c:99
#define OP_DB_LEAF
Leaf of combination, db fmt.
Definition: raytrace.h:1139
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#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
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
#define TREE_NULL
Definition: raytrace.h:1181
uint8_t * ext_buf
Definition: parse.h:216
void db_free_tree(union tree *tp, struct resource *resp)
Definition: db_tree.c:1296
matp_t tl_mat
xform matp, NULL ==> identity
Definition: raytrace.h:1173
struct bu_vls shader
Definition: raytrace.h:950
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
#define OP_REGION
Leaf: tr_stp -> combined_tree_state.
Definition: raytrace.h:1131
#define REGION_FASTGEN_VOLUME
Definition: raytrace.h:555
struct tree::tree_node tr_b
matp_t bn_mat_dup(const mat_t in)
Definition: mat.c:1046
#define UNUSED(parameter)
Definition: common.h:239
#define OP_GUARD
Unary: not L, or else!
Definition: raytrace.h:1135
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
union tree * db_mkbool_tree(struct rt_tree_array *rt_tree_array, size_t howfar, struct resource *resp)
Definition: db_comb.c:954
struct bu_vls material
Definition: raytrace.h:951
struct mater * rt_material_head(void)
Definition: mater.c:243
#define STAT_SCALE
Definition: db_comb.c:57
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
void rt_comb_ifree(struct rt_db_internal *ip)
Definition: db_comb.c:844
struct tree::tree_db_leaf tr_l
union tree * tb_right
Definition: raytrace.h:1150
#define ZERO(val)
Definition: units.c:38
void * idb_ptr
Definition: raytrace.h:195
void db_wrap_v4_external(struct bu_external *op, const char *name)
Definition: db_comb.c:885
#define REGION_NON_FASTGEN
Definition: raytrace.h:553
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
const struct rt_functab OBJ[]
Definition: table.c:159
#define RT_CK_RESOURCE(_p)
Definition: raytrace.h:1490
Definition: op.h:35
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
#define BU_ASSERT_PTR(_lhs, _relation, _rhs)
Definition: defines.h:227
HIDDEN fastf_t bin(fastf_t val, fastf_t step)
Definition: nmg_tri_mc.c:461
union tree * db_dup_subtree(const union tree *tp, struct resource *resp)
Definition: db_tree.c:1190
#define RT_GET_TREE(_tp, _res)
Definition: raytrace.h:1210
#define RT_COMB_INTERNAL_INIT(_p)
Definition: raytrace.h:960
short flip_short(short s)
Definition: db_flip.c:47
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
int db_ck_left_heavy_tree(const union tree *tp, int no_unions)
Definition: db_comb.c:898
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define BU_EXTERNAL_INIT(_p)
Definition: parse.h:229
int bu_shader_to_key_eq(const char *in, struct bu_vls *vls)
Definition: parse.c:2279
char is_fastgen
REGION_NON_FASTGEN/_PLATE/_VOLUME.
Definition: raytrace.h:940
#define RT_FREE_COMB_INTERNAL(_p)
Definition: raytrace.h:986
int dbi_version
PRIVATE: use db_version()
Definition: raytrace.h:824
#define BU_ASSERT_SIZE_T(_lhs, _relation, _rhs)
Definition: defines.h:253
int db_ck_v4gift_tree(const union tree *tp)
Definition: db_comb.c:927
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int db_comb_mvall(struct directory *dp, struct db_i *dbip, const char *old_name, const char *new_name, struct bu_ptbl *stack)
Definition: db_comb.c:1107
#define RT_CK_TREE(_p)
Definition: raytrace.h:1182
char rgb_valid
!0 ==> rgb[] has valid color
Definition: raytrace.h:947
#define BU_CK_EXTERNAL(_p)
Definition: parse.h:224
void db_tree_describe(struct bu_vls *vls, const union tree *tp, int indented, int lvl, double mm2local)
Definition: db_comb.c:679
int rt_comb_import4(struct rt_db_internal *ip, const struct bu_external *ep, const mat_t matrix, const struct db_i *dbip, struct resource *resp)
Definition: db_comb.c:179
void bu_vls_spaces(struct bu_vls *vp, size_t cnt)
Definition: vls.c:721
#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
size_t ext_nbytes
Definition: parse.h:210
#define DEBUG_TREEWALK
22 Database tree traversal
Definition: raytrace.h:107
HIDDEN void verbose(struct human_data_t *dude)
Definition: human.c:2008
int d_flags
flags
Definition: raytrace.h:869
Definition: vls.h:56
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
#define OP_UNION
Binary: L union R.
Definition: raytrace.h:1127
#define OP_NOT
Unary: not L.
Definition: raytrace.h:1134
#define STAT_XLATE
Definition: db_comb.c:55
#define STAT_ROT
Definition: db_comb.c:54
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
#define bu_strlcat(dst, src, size)
Definition: str.h:50
#define bu_strdup(s)
Definition: str.h:71
#define M
Definition: msr.c:52
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126