BRL-CAD
reg.c
Go to the documentation of this file.
1 /* R E G . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1987-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/reg.c
21  *
22  * Library for writing MGED databases from arbitrary procedures.
23  *
24  * This module contains routines to create combinations, and regions.
25  *
26  * It is expected that this library will grow as experience is gained.
27  *
28  */
29 
30 #include "common.h"
31 
32 #include <math.h>
33 #include <string.h>
34 #include "bio.h"
35 
36 #include "vmath.h"
37 #include "bn.h"
38 #include "raytrace.h"
39 #include "wdb.h"
40 
41 /**
42  * Given a list of wmember structures, build a tree that performs the
43  * boolean operations in the given sequence. No GIFT semantics or
44  * precedence is provided. For that, use mk_tree_gift().
45  */
46 void
47 mk_tree_pure(struct rt_comb_internal *comb, struct bu_list *member_hd)
48 {
49  struct wmember *wp;
50 
51  for (BU_LIST_FOR(wp, wmember, member_hd)) {
52  union tree *leafp, *nodep;
53 
54  WDB_CK_WMEMBER(wp);
55 
56  BU_ALLOC(leafp, union tree);
57  RT_TREE_INIT(leafp);
58  leafp->tr_l.tl_op = OP_DB_LEAF;
59  leafp->tr_l.tl_name = bu_strdup(wp->wm_name);
60  if (!bn_mat_is_identity(wp->wm_mat)) {
61  leafp->tr_l.tl_mat = bn_mat_dup(wp->wm_mat);
62  }
63 
64  if (!comb->tree) {
65  comb->tree = leafp;
66  continue;
67  }
68  /* Build a left-heavy tree */
69  BU_ALLOC(nodep, union tree);
70  RT_TREE_INIT(nodep);
71  switch (wp->wm_op) {
72  case WMOP_UNION:
73  nodep->tr_b.tb_op = OP_UNION;
74  break;
75  case WMOP_INTERSECT:
76  nodep->tr_b.tb_op = OP_INTERSECT;
77  break;
78  case WMOP_SUBTRACT:
79  nodep->tr_b.tb_op = OP_SUBTRACT;
80  break;
81  default:
82  bu_bomb("mk_tree_pure() bad wm_op");
83  }
84  nodep->tr_b.tb_left = comb->tree;
85  nodep->tr_b.tb_right = leafp;
86  comb->tree = nodep;
87  }
88 }
89 
90 
91 /**
92  * Add some nodes to a new or existing combination's tree, with GIFT
93  * precedence and semantics.
94  *
95  * NON-PARALLEL due to rt_uniresource
96  *
97  * Returns -
98  * -1 ERROR
99  * 0 OK
100  */
101 int
102 mk_tree_gift(struct rt_comb_internal *comb, struct bu_list *member_hd)
103 {
104  struct wmember *wp;
105  union tree *tp;
106  struct rt_tree_array *tree_list;
107  size_t node_count;
108  size_t actual_count;
109  int new_nodes;
110 
111  new_nodes = bu_list_len(member_hd);
112  if (new_nodes <= 0)
113  return 0; /* OK, nothing to do */
114 
115  if (comb->tree && db_ck_v4gift_tree(comb->tree) < 0) {
117  if (db_ck_v4gift_tree(comb->tree) < 0) {
118  bu_log("mk_tree_gift() Cannot flatten tree for editing\n");
119  return -1;
120  }
121  }
122 
123  /* make space for an extra leaf */
124  node_count = db_tree_nleaves(comb->tree);
125  tree_list = (struct rt_tree_array *)bu_calloc((size_t)node_count + (size_t)new_nodes,
126  sizeof(struct rt_tree_array), "tree list");
127 
128  /* flatten tree */
129  if (comb->tree) {
130  /* Release storage for non-leaf nodes, steal leaves */
131  actual_count = (struct rt_tree_array *)db_flatten_tree(tree_list, comb->tree, OP_UNION, 1, &rt_uniresource) - tree_list;
132  BU_ASSERT_SIZE_T(actual_count, ==, node_count);
133  comb->tree = TREE_NULL;
134  } else {
135  actual_count = 0;
136  }
137 
138  /* Add new members to the array */
139  for (BU_LIST_FOR(wp, wmember, member_hd)) {
140  WDB_CK_WMEMBER(wp);
141 
142  switch (wp->wm_op) {
143  case WMOP_INTERSECT:
144  tree_list[node_count].tl_op = OP_INTERSECT;
145  break;
146  case WMOP_SUBTRACT:
147  tree_list[node_count].tl_op = OP_SUBTRACT;
148  break;
149  default:
150  bu_log("mk_tree_gift() unrecognized relation %c (assuming UNION)\n", wp->wm_op);
151  /* Fall through */
152  case WMOP_UNION:
153  tree_list[node_count].tl_op = OP_UNION;
154  break;
155  }
156 
157  /* make new leaf node, and insert at end of array */
158  BU_ALLOC(tp, union tree);
159  RT_TREE_INIT(tp);
160  tree_list[node_count++].tl_tree = tp;
161  tp->tr_l.tl_op = OP_DB_LEAF;
162  tp->tr_l.tl_name = bu_strdup(wp->wm_name);
163  if (!bn_mat_is_identity(wp->wm_mat)) {
164  tp->tr_l.tl_mat = bn_mat_dup(wp->wm_mat);
165  } else {
166  tp->tr_l.tl_mat = (matp_t)NULL;
167  }
168  }
169  BU_ASSERT_SIZE_T(node_count, ==, actual_count + (size_t)new_nodes);
170 
171  /* rebuild the tree with GIFT semantics */
172  comb->tree = (union tree *)db_mkgift_tree(tree_list, node_count, &rt_uniresource);
173 
174  bu_free((char *)tree_list, "mk_tree_gift: tree_list");
175 
176  return 0; /* OK */
177 }
178 
179 
180 struct wmember *
182  const char *name,
183  struct bu_list *headp,
184  mat_t mat,
185  int op)
186 {
187  struct wmember *wp;
188 
189  BU_ALLOC(wp, struct wmember);
190  wp->l.magic = WMEMBER_MAGIC;
191  wp->wm_name = bu_strdup(name);
192  switch (op) {
193  case WMOP_UNION:
194  case WMOP_INTERSECT:
195  case WMOP_SUBTRACT:
196  wp->wm_op = op;
197  break;
198  default:
199  bu_log("mk_addmember() op=x%x is bad\n", op);
200  return WMEMBER_NULL;
201  }
202 
203  /* if the user gave a matrix, use it. otherwise use identity matrix*/
204  if (mat) {
205  MAT_COPY(wp->wm_mat, mat);
206  } else {
207  MAT_IDN(wp->wm_mat);
208  }
209 
210  /* Append to end of doubly linked list */
211  BU_LIST_INSERT(headp, &wp->l);
212  return wp;
213 }
214 
215 void
216 mk_freemembers(struct bu_list *headp)
217 {
218  struct wmember *wp;
219 
220  while (BU_LIST_WHILE(wp, wmember, headp)) {
221  WDB_CK_WMEMBER(wp);
222  BU_LIST_DEQUEUE(&wp->l);
223  bu_free((char *)wp->wm_name, "wm_name");
224  bu_free((char *)wp, "wmember");
225  }
226 }
227 
228 
229 int
231  struct rt_wdb *wdbp,
232  const char *combname,
233  struct bu_list *headp,
234  int region_kind,
235  const char *shadername,
236  const char *shaderargs,
237  const unsigned char *rgb,
238  int id,
239  int air,
240  int material,
241  int los,
242  int inherit,
243  int append_ok,
244  int gift_semantics)
245 {
246  struct rt_db_internal intern;
247  struct rt_comb_internal *comb;
248  int fresh_combination;
249 
250  RT_CK_WDB(wdbp);
251 
252  RT_DB_INTERNAL_INIT(&intern);
253 
254  if (append_ok &&
255  wdb_import(wdbp, &intern, combname, (matp_t)NULL) >= 0) {
256  /* We retrieved an existing object, append to it */
257  comb = (struct rt_comb_internal *)intern.idb_ptr;
258  RT_CK_COMB(comb);
259 
260  fresh_combination = 0;
261  } else {
262  /* Create a fresh new object for export */
263  BU_ALLOC(comb, struct rt_comb_internal);
264  RT_COMB_INTERNAL_INIT(comb);
265 
266  intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
267  intern.idb_type = ID_COMBINATION;
268  intern.idb_ptr = (void *)comb;
269  intern.idb_meth = &OBJ[ID_COMBINATION];
270 
271  fresh_combination = 1;
272  }
273 
274  if (gift_semantics)
275  mk_tree_gift(comb, headp);
276  else
277  mk_tree_pure(comb, headp);
278 
279  /* Release the wmember list dynamic storage */
280  mk_freemembers(headp);
281 
282  /* Don't change these things when appending to existing combination */
283  if (fresh_combination) {
284  if (region_kind) {
285  comb->region_flag = 1;
286  switch (region_kind) {
287  case 'P':
289  break;
290  case 'V':
292  break;
293  case 'R':
294  case 1:
295  /* Regular non-FASTGEN Region */
296  break;
297  default:
298  bu_log("mk_comb(%s) unknown region_kind=%d (%c), assuming normal non-FASTGEN\n",
299  combname, region_kind, region_kind);
300  }
301  }
302  if (shadername) bu_vls_strcat(&comb->shader, shadername);
303  if (shaderargs) {
304  bu_vls_strcat(&comb->shader, " ");
305  bu_vls_strcat(&comb->shader, shaderargs);
306  /* Convert to Tcl form if necessary. Use heuristics */
307  if (strchr(shaderargs, '=') != NULL
308  && strchr(shaderargs, '{') == NULL)
309  {
310  struct bu_vls old = BU_VLS_INIT_ZERO;
311 
312  bu_vls_vlscatzap(&old, &comb->shader);
313  if (bu_shader_to_list(bu_vls_addr(&old), &comb->shader))
314  bu_log("Unable to convert shader string '%s %s'\n", shadername, shaderargs);
315  bu_vls_free(&old);
316  }
317  }
318 
319  if (rgb) {
320  comb->rgb_valid = 1;
321  comb->rgb[0] = rgb[0];
322  comb->rgb[1] = rgb[1];
323  comb->rgb[2] = rgb[2];
324  }
325 
326  comb->region_id = id;
327  comb->aircode = air;
328  comb->GIFTmater = material;
329  comb->los = los;
330 
331  comb->inherit = inherit;
332  }
333 
334  /* The internal representation will be freed */
335  return wdb_put_internal(wdbp, combname, &intern, mk_conv2mm);
336 }
337 
338 
339 int
340 mk_comb1(struct rt_wdb *wdbp,
341  const char *combname,
342  const char *membname,
343  int regflag)
344 {
345  struct bu_list head;
346 
347  BU_LIST_INIT(&head);
348  if (mk_addmember(membname, &head, NULL, WMOP_UNION) == WMEMBER_NULL)
349  return -2;
350  return mk_comb(wdbp, combname, &head, regflag,
351  (char *)NULL, (char *)NULL, (unsigned char *)NULL,
352  0, 0, 0, 0,
353  0, 0, 0);
354 }
355 
356 int
358  struct rt_wdb *wdbp,
359  const char *combname,
360  const char *membname,
361  const char *shadername,
362  const char *shaderargs,
363  const unsigned char *rgb)
364 {
365  struct bu_list head;
366 
367  BU_LIST_INIT(&head);
368  if (mk_addmember(membname, &head, NULL, WMOP_UNION) == WMEMBER_NULL)
369  return -2;
370  return mk_comb(wdbp, combname, &head, 1, shadername, shaderargs,
371  rgb, 0, 0, 0, 0, 0, 0, 0);
372 }
373 
374 
375 /*
376  * Local Variables:
377  * mode: C
378  * tab-width: 8
379  * indent-tabs-mode: t
380  * c-file-style: "stroustrup"
381  * End:
382  * ex: shiftwidth=4 tabstop=8
383  */
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
#define WDB_CK_WMEMBER(_p)
Definition: wdb.h:74
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
Definition: list.h:118
#define REGION_FASTGEN_PLATE
Definition: raytrace.h:554
int mk_tree_gift(struct rt_comb_internal *comb, struct bu_list *member_hd)
Definition: reg.c:102
int tb_op
non-leaf
Definition: raytrace.h:1147
size_t db_tree_nleaves(const union tree *tp)
Definition: db_comb.c:99
Definition: clone.c:90
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
#define RT_CK_COMB(_p)
Definition: raytrace.h:955
union tree * tl_tree
Definition: raytrace.h:1247
Definition: wdb.h:64
Header file for the BRL-CAD common definitions.
#define WMOP_SUBTRACT
Definition: wdb.h:886
union tree * db_mkgift_tree(struct rt_tree_array *trees, size_t subtreecount, struct resource *resp)
Definition: db_comb.c:1016
unsigned char rgb[3]
Definition: raytrace.h:948
#define WMOP_UNION
Definition: wdb.h:887
#define ID_COMBINATION
Combination Record.
Definition: raytrace.h:499
struct bu_list l
Definition: wdb.h:65
#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
#define RT_CK_WDB(_p)
Definition: raytrace.h:1292
struct rt_tree_array * db_flatten_tree(struct rt_tree_array *rt_tree_array, union tree *tp, int op, int avail, struct resource *resp)
Definition: db_comb.c:138
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 WMEMBER_NULL
Definition: wdb.h:73
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
void mk_tree_pure(struct rt_comb_internal *comb, struct bu_list *member_hd)
Definition: reg.c:47
#define WMOP_INTERSECT
Definition: wdb.h:885
#define OP_DB_LEAF
Leaf of combination, db fmt.
Definition: raytrace.h:1139
#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 RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define TREE_NULL
Definition: raytrace.h:1181
int mk_region1(struct rt_wdb *wdbp, const char *combname, const char *membname, const char *shadername, const char *shaderargs, const unsigned char *rgb)
Definition: reg.c:357
matp_t tl_mat
xform matp, NULL ==> identity
Definition: raytrace.h:1173
struct bu_vls shader
Definition: raytrace.h:950
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
#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
struct wmember * mk_addmember(const char *name, struct bu_list *headp, mat_t mat, int op)
Definition: reg.c:181
double mk_conv2mm
Conversion factor to mm.
Definition: units.c:37
char * wm_name
Definition: wdb.h:68
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
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
int wm_op
Boolean operation.
Definition: wdb.h:66
int mk_comb(struct rt_wdb *wdbp, const char *combname, struct bu_list *headp, int region_kind, const char *shadername, const char *shaderargs, const unsigned char *rgb, int id, int air, int material, int los, int inherit, int append_ok, int gift_semantics)
Definition: reg.c:230
struct tree::tree_db_leaf tr_l
union tree * tb_right
Definition: raytrace.h:1150
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * idb_ptr
Definition: raytrace.h:195
int mk_comb1(struct rt_wdb *wdbp, const char *combname, const char *membname, int regflag)
Definition: reg.c:340
const struct rt_functab OBJ[]
Definition: table.c:159
#define WMEMBER_MAGIC
Definition: magic.h:215
#define RT_COMB_INTERNAL_INIT(_p)
Definition: raytrace.h:960
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
int wdb_import(struct rt_wdb *wdbp, struct rt_db_internal *internp, const char *name, const mat_t mat)
Definition: wdb.c:92
int bu_list_len(const struct bu_list *hd)
char is_fastgen
REGION_NON_FASTGEN/_PLATE/_VOLUME.
Definition: raytrace.h:940
#define BU_ASSERT_SIZE_T(_lhs, _relation, _rhs)
Definition: defines.h:253
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
char rgb_valid
!0 ==> rgb[] has valid color
Definition: raytrace.h:947
void mk_freemembers(struct bu_list *headp)
Definition: reg.c:216
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
int tl_op
leaf, OP_DB_LEAF
Definition: raytrace.h:1172
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
mat_t wm_mat
FIXME: Should be a matp_t.
Definition: wdb.h:67
Definition: vls.h:56
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
#define OP_UNION
Binary: L union R.
Definition: raytrace.h:1127
int db_ck_v4gift_tree(const union tree *tp)
Definition: db_comb.c:927
void bu_vls_vlscatzap(struct bu_vls *dest, struct bu_vls *src)
Definition: vls.c:433
#define bu_strdup(s)
Definition: str.h:71