BRL-CAD
combmem.c
Go to the documentation of this file.
1 /* C O M B M E M . 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/combmem.c
21  *
22  * The combmem command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 
32 #include "bu/getopt.h"
33 #include "./ged_private.h"
34 
35 enum etypes {
44 };
45 
46 
47 /**
48  * Given the azimuth, elevation and twist angles, calculate the
49  * rotation part of a 4x4 matrix.
50  */
51 HIDDEN void
52 combmem_mat_aet(matp_t matp, fastf_t az, fastf_t el, fastf_t tw)
53 {
54  fastf_t cos_az, sin_az;
55  fastf_t cos_el, sin_el;
56  fastf_t cos_tw, sin_tw;
57 
58  if (!matp)
59  return;
60 
61  cos_az = cos(az);
62  sin_az = sin(az);
63  cos_el = cos(el);
64  sin_el = sin(el);
65  cos_tw = cos(tw);
66  sin_tw = sin(tw);
67 
68  matp[0] = cos_az*cos_el;
69  matp[1] = -cos_el*sin_az;
70  matp[2] = -sin_el;
71  matp[3] = 0.0;
72  matp[4] = cos_tw*sin_az - cos_az*sin_el*sin_tw;
73  matp[5] = cos_az*cos_tw + sin_az*sin_el*sin_tw;
74  matp[6] = -cos_el*sin_tw;
75  matp[7] = 0.0;
76  matp[8] = cos_az*cos_tw*sin_el + sin_az*sin_tw;
77  matp[9] = -cos_tw*sin_az*sin_el + cos_az*sin_tw;
78  matp[10] = cos_el*cos_tw;
79  matp[11] = 0.0;
80 
81  /* no perspective */
82  matp[12] = matp[13] = matp[14] = 0.0;
83 
84  /* overall scale of 1 */
85  matp[15] = 1.0;
86 }
87 
88 
89 /**
90  * Disassemble the given rotation matrix into az, el, tw.
91  */
92 HIDDEN void
93 combmem_disassemble_rmat(matp_t matp, fastf_t *az, fastf_t *el, fastf_t *tw)
94 {
95  fastf_t cos_az, sin_az;
96  fastf_t cos_el, sin_el;
97  fastf_t cos_tw, sin_tw;
98 
99  sin_el = -matp[2];
100  cos_el = sqrt(1.0 - (sin_el*sin_el));
101 
102  if (NEAR_ZERO(cos_el, 0.000001)) {
103  cos_az = matp[5];
104  cos_tw = 1.0;
105  sin_az = matp[4];
106  sin_tw = 0.0;
107  } else {
108  cos_az = matp[0] / cos_el;
109  cos_tw = matp[10] / cos_el;
110  sin_az = -matp[1] / cos_el;
111  sin_tw = -matp[6] / cos_el;
112  }
113 
114  if (NEAR_EQUAL(cos_az, 1.0, 0.000001) ||
115  NEAR_EQUAL(cos_az, -1.0, 0.000001)) {
116  *az= 0.0;
117  } else
118  *az = acos(cos_az);
119 
120  if (NEAR_EQUAL(cos_el, 1.0, 0.000001) ||
121  NEAR_EQUAL(cos_el, -1.0, 0.000001)) {
122  *el= 0.0;
123  } else
124  *el = acos(cos_el);
125 
126  if (NEAR_EQUAL(cos_tw, 1.0, 0.000001) ||
127  NEAR_EQUAL(cos_tw, -1.0, 0.000001)) {
128  *tw= 0.0;
129  } else
130  *tw = acos(cos_tw);
131 
132  if (sin_az < 0.0)
133  *az *= -1.0;
134  if (sin_el < 0.0)
135  *el *= -1.0;
136  if (sin_tw < 0.0)
137  *tw *= -1.0;
138 }
139 
140 
141 /**
142  * Disassemble the given matrix into az, el, tw, tx, ty, tz, sa, sx, sy and sz.
143  */
144 HIDDEN int
145 combmem_disassemble_mat(matp_t matp, fastf_t *az, fastf_t *el, fastf_t *tw, fastf_t *tx, fastf_t *ty, fastf_t *tz, fastf_t *sa, fastf_t *sx, fastf_t *sy, fastf_t *sz)
146 {
147  mat_t m;
148 
149  if (!matp)
150  return 1;
151 
152  MAT_COPY(m, matp);
153 
154  *sa = 1.0 / m[MSA];
155 
156  *sx = sqrt(m[0]*m[0] + m[4]*m[4] + m[8]*m[8]);
157  *sy = sqrt(m[1]*m[1] + m[5]*m[5] + m[9]*m[9]);
158  *sz = sqrt(m[2]*m[2] + m[6]*m[6] + m[10]*m[10]);
159 
160  if (!NEAR_EQUAL(*sx, 1.0, VUNITIZE_TOL)) {
161  m[0] /= *sx;
162  m[4] /= *sx;
163  m[8] /= *sx;
164  }
165 
166  if (!NEAR_EQUAL(*sy, 1.0, VUNITIZE_TOL)) {
167  m[1] /= *sy;
168  m[5] /= *sy;
169  m[9] /= *sy;
170  }
171 
172  if (!NEAR_EQUAL(*sz, 1.0, VUNITIZE_TOL)) {
173  m[2] /= *sz;
174  m[6] /= *sz;
175  m[10] /= *sz;
176  }
177 
178  if (bn_mat_ck("combmem_disassemble_mat", m)) {
179  *az = 0.0;
180  *el = 0.0;
181  *tw = 0.0;
182  *tx = 0.0;
183  *ty = 0.0;
184  *tz = 0.0;
185  *sa = 1.0;
186  *sx = 1.0;
187  *sy = 1.0;
188  *sz = 1.0;
189 
190  /* The upper left 3x3 is not a rotation matrix */
191  return 1;
192  }
193 
194  *tx = m[MDX];
195  *ty = m[MDY];
196  *tz = m[MDZ];
197 
198  combmem_disassemble_rmat(m, az, el, tw);
199 
200  return 0; /* OK */
201 }
202 
203 
204 /**
205  * Assemble the given aetvec, tvec and svec into a 4x4 matrix using key_pt for rotations and scale.
206  */
207 HIDDEN void
208 combmem_assemble_mat(matp_t matp, vect_t aetvec, vect_t tvec, hvect_t svec, point_t key_pt, int sflag)
209 {
210  mat_t mat_aet_about_pt;
211  mat_t mat_aet;
212  mat_t mat_scale;
213  mat_t xlate;
214  mat_t tmp;
215 
216  if (!matp)
217  return;
218 
219  if (ZERO(svec[X]) ||
220  ZERO(svec[Y]) ||
221  ZERO(svec[Z]) ||
222  ZERO(svec[W])) {
223  return;
224  }
225 
226  combmem_mat_aet(mat_aet, aetvec[X], aetvec[Y], aetvec[Z]);
227  bn_mat_xform_about_pt(mat_aet_about_pt, mat_aet, key_pt);
228 
229  MAT_IDN(mat_scale);
230 
231  if (sflag) {
232  if (!NEAR_EQUAL(svec[X], 1.0, VUNITIZE_TOL)) {
233  mat_scale[0] *= svec[X];
234  mat_scale[4] *= svec[X];
235  mat_scale[8] *= svec[X];
236  }
237 
238  if (!NEAR_EQUAL(svec[Y], 1.0, VUNITIZE_TOL)) {
239  mat_scale[1] *= svec[Y];
240  mat_scale[5] *= svec[Y];
241  mat_scale[9] *= svec[Y];
242  }
243 
244  if (!NEAR_EQUAL(svec[Z], 1.0, VUNITIZE_TOL)) {
245  mat_scale[2] *= svec[Z];
246  mat_scale[6] *= svec[Z];
247  mat_scale[10] *= svec[Z];
248  }
249  }
250 
251  if (!NEAR_EQUAL(svec[W], 1.0, VUNITIZE_TOL)) {
252  mat_scale[MSA] *= 1.0 / svec[W];
253  }
254 
255  MAT_IDN(xlate);
256  MAT_DELTAS_VEC_NEG(xlate, key_pt);
257 
258  bn_mat_mul(tmp, mat_scale, xlate);
259  MAT_DELTAS_VEC(xlate, key_pt);
260  bn_mat_mul(mat_scale, xlate, tmp);
261 
262  MAT_IDN(xlate);
263  MAT_DELTAS_VEC(xlate, tvec);
264 
265  bn_mat_mul(tmp, mat_scale, mat_aet_about_pt);
266  bn_mat_mul(matp, xlate, tmp);
267 }
268 
269 
270 HIDDEN void
271 combmem_vls_print_member_info(struct ged *gedp, char op, union tree *itp, enum etypes etype)
272 {
273  fastf_t az, el, tw;
274  fastf_t tx, ty, tz;
275  fastf_t sa, sx, sy, sz;
276 
277  switch (etype) {
278  case ETYPES_ABS:
279  if (!itp->tr_l.tl_mat) {
280  bu_vls_printf(gedp->ged_result_str, "%c {%s} 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0",
281  op, itp->tr_l.tl_name);
282  } else {
283  if (combmem_disassemble_mat(itp->tr_l.tl_mat, &az, &el, &tw, &tx, &ty, &tz, &sa, &sx, &sy, &sz))
284  bu_log("Found bad matrix for %s\n", itp->tr_l.tl_name);
285 
286  bu_vls_printf(gedp->ged_result_str, "%c {%s} %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf 0.0 0.0 0.0",
287  op, itp->tr_l.tl_name,
288  az * RAD2DEG,
289  el * RAD2DEG,
290  tw * RAD2DEG,
291  tx, ty, tz,
292  sa, sx, sy, sz);
293  }
294 
295  break;
296  case ETYPES_REL:
297  bu_vls_printf(gedp->ged_result_str, "%c {%s} 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0",
298  op, itp->tr_l.tl_name);
299  break;
300  case ETYPES_ROT_AET:
301  bu_vls_printf(gedp->ged_result_str, "%c {%s} 0.0 0.0 0.0 0.0 0.0 0.0",
302  op, itp->tr_l.tl_name);
303  break;
304  case ETYPES_ROT_XYZ:
305  bu_vls_printf(gedp->ged_result_str, "%c {%s} 0.0 0.0 0.0 0.0 0.0 0.0",
306  op, itp->tr_l.tl_name);
307  break;
309  bu_vls_printf(gedp->ged_result_str, "%c {%s} 0.0 0.0 0.0 0.0 0.0 0.0 0.0",
310  op, itp->tr_l.tl_name);
311  break;
312  case ETYPES_TRA:
313  bu_vls_printf(gedp->ged_result_str, "%c {%s} 0.0 0.0 0.0",
314  op, itp->tr_l.tl_name);
315  break;
316  case ETYPES_SCA:
317  bu_vls_printf(gedp->ged_result_str, "%c {%s} 1.0 1.0 1.0 1.0 0.0 0.0 0.0",
318  op, itp->tr_l.tl_name);
319  default:
320  break;
321  }
322 
323 }
324 
325 
326 #define COMBMEM_GETCOMBTREE(_gedp, _cmd, _name, _dp, _intern, _ntp, _rt_tree_array, _node_count) { \
327  struct rt_comb_internal *_comb; \
328  \
329  if ((_dp = db_lookup((_gedp)->ged_wdbp->dbip, (_name), LOOKUP_NOISY)) == RT_DIR_NULL) { \
330  bu_vls_printf(gedp->ged_result_str, "%s: Warning - %s not found in database.\n", (_cmd), (_name)); \
331  return GED_ERROR; \
332  } \
333  \
334  if (!(_dp->d_flags & RT_DIR_COMB)) { \
335  bu_vls_printf((_gedp)->ged_result_str, "%s: Warning - %s not a combination\n", (_cmd), (_name)); \
336  return GED_ERROR; \
337  } \
338  \
339  if (rt_db_get_internal(&(_intern), _dp, (_gedp)->ged_wdbp->dbip, (matp_t)NULL, &rt_uniresource) < 0) { \
340  bu_vls_printf((_gedp)->ged_result_str, "Database read error, aborting"); \
341  return GED_ERROR; \
342  } \
343  \
344  _comb = (struct rt_comb_internal *)(_intern).idb_ptr; \
345  RT_CK_COMB(_comb); \
346  if (_comb->tree) { \
347  (_ntp) = db_dup_subtree(_comb->tree, &rt_uniresource); \
348  RT_CK_TREE(_ntp); \
349  \
350  /* Convert to "v4 / GIFT style", so that the flatten makes sense. */ \
351  if (db_ck_v4gift_tree(_ntp) < 0) \
352  db_non_union_push((_ntp), &rt_uniresource); \
353  RT_CK_TREE(_ntp); \
354  \
355  (_node_count) = db_tree_nleaves(_ntp); \
356  (_rt_tree_array) = (struct rt_tree_array *)bu_calloc((_node_count), sizeof(struct rt_tree_array), "rt_tree_array"); \
357  \
358  /* \
359  * free=0 means that the tree won't have any leaf nodes freed. \
360  */ \
361  (void)db_flatten_tree((_rt_tree_array), (_ntp), OP_UNION, 0, &rt_uniresource); \
362  } else { \
363  (_ntp) = TREE_NULL; \
364  (_node_count) = 0; \
365  (_rt_tree_array) = (struct rt_tree_array *)0; \
366  } \
367  }
368 
369 
370 HIDDEN int
371 combmem_get(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
372 {
373  struct directory *dp;
374  struct rt_db_internal intern;
375  union tree *ntp;
377  size_t i;
378  size_t node_count;
379 
380  if (argc < 2) {
381  bu_vls_printf(gedp->ged_result_str, "ERROR argument missing after [%s]\n", argv[0]);
382  return GED_ERROR;
383  }
384 
385  COMBMEM_GETCOMBTREE(gedp, argv[0], argv[1], dp, intern, ntp, rt_tree_array, node_count);
386 
387  for (i = 0; i < node_count; i++) {
388  union tree *itp = rt_tree_array[i].tl_tree;
389  char op = '\0';
390 
391  RT_CK_TREE(itp);
392  BU_ASSERT_LONG(itp->tr_op, ==, OP_DB_LEAF);
393  BU_ASSERT_PTR(itp->tr_l.tl_name, !=, NULL);
394 
395  switch (rt_tree_array[i].tl_op) {
396  case OP_INTERSECT:
397  op = DB_OP_INTERSECT;
398  break;
399  case OP_SUBTRACT:
400  op = DB_OP_SUBTRACT;
401  break;
402  case OP_UNION:
403  op = DB_OP_UNION;
404  break;
405  default:
406  bu_bomb("combmem_get() corrupt rt_tree_array");
407  }
408 
409  combmem_vls_print_member_info(gedp, op, itp, etype);
410  bu_vls_printf(gedp->ged_result_str, "\n");
411  }
412 
413  rt_db_free_internal(&intern);
414  if (rt_tree_array) bu_free((void *)rt_tree_array, "rt_tree_array");
416  return GED_OK;
417 }
418 
419 
420 #define COMBMEM_SET_PART_I(_gedp, _argc, _cmd, _name, _num_params, _intern, _dp, _comb, _node_count, _rt_tree_array) { \
421  if (rt_db_get_internal(&(_intern), (_dp), (_gedp)->ged_wdbp->dbip, (matp_t)NULL, &rt_uniresource) < 0) { \
422  bu_vls_printf((_gedp)->ged_result_str, "Database read error, aborting"); \
423  return GED_ERROR; \
424  } \
425  \
426  (_comb) = (struct rt_comb_internal *)(_intern).idb_ptr; \
427  RT_CK_COMB((_comb)); \
428  (_node_count) = ((_argc) - 2) / (_num_params); /* integer division */ \
429  if (_node_count) { \
430  (_rt_tree_array) = (struct rt_tree_array *)bu_calloc((_node_count), sizeof(struct rt_tree_array), "tree list"); \
431  } else { \
432  (_rt_tree_array) = (struct rt_tree_array *)0; \
433  } \
434  }
435 
436 
437 #define COMBMEM_SET_PART_II(_gedp, _opstr, _rt_tree_array_index, _mat) { \
438  db_op_t combmem_set_part_ii_op = db_str2op((_opstr)); \
439  \
440  /* Add it to the combination */ \
441  switch (combmem_set_part_ii_op) { \
442  case DB_OP_INTERSECT: \
443  (_rt_tree_array_index).tl_op = OP_INTERSECT; \
444  break; \
445  case DB_OP_SUBTRACT: \
446  (_rt_tree_array_index).tl_op = OP_SUBTRACT; \
447  break; \
448  default: \
449  bu_vls_printf((_gedp)->ged_result_str, "combmem_set: unrecognized relation %c (assuming UNION)\n", (_opstr)[0]); \
450  case DB_OP_UNION: \
451  (_rt_tree_array_index).tl_op = OP_UNION; \
452  break; \
453  } \
454  \
455  MAT_IDN((_mat)); \
456  }
457 
458 
459 #define COMBMEM_SET_PART_III(_tp, _tree, _rt_tree_array_index, _name) \
460  (_rt_tree_array_index).tl_tree = (_tp); \
461  (_tp)->tr_l.tl_op = OP_DB_LEAF; \
462  (_tp)->tr_l.tl_name = bu_strdup(_name); \
463  (_tp)->tr_l.tl_mat = (matp_t)bu_calloc(1, sizeof(mat_t), "combmem_set: mat");
464 
465 
466 #define COMBMEM_SET_PART_IV(_gedp, _comb, _tree_index, _intern, _final_tree, _node_count, _dp, _rt_tree_array, _old_intern, _old_rt_tree_array, _old_ntp) \
467  db_free_tree((_comb)->tree, &rt_uniresource); \
468  (_comb)->tree = NULL; \
469  \
470  if ((_tree_index)) \
471  (_final_tree) = (union tree *)db_mkgift_tree((_rt_tree_array), (_node_count), &rt_uniresource); \
472  else \
473  (_final_tree) = TREE_NULL; \
474  \
475  RT_DB_INTERNAL_INIT(&(_intern)); \
476  (_intern).idb_major_type = DB5_MAJORTYPE_BRLCAD; \
477  (_intern).idb_type = ID_COMBINATION; \
478  (_intern).idb_meth = &OBJ[ID_COMBINATION]; \
479  (_intern).idb_ptr = (void *)(_comb); \
480  (_comb)->tree = (_final_tree); \
481  \
482  if (rt_db_put_internal((_dp), (_gedp)->ged_wdbp->dbip, &(_intern), &rt_uniresource) < 0) { \
483  bu_vls_printf((_gedp)->ged_result_str, "Unable to write new combination into database.\n"); \
484  \
485  rt_db_free_internal(&(_old_intern)); \
486  if (_old_rt_tree_array) \
487  bu_free((void *)(_old_rt_tree_array), "rt_tree_array"); \
488  db_free_tree((_old_ntp), &rt_uniresource); \
489  \
490  return GED_ERROR; \
491  } \
492  \
493  rt_db_free_internal(&(_old_intern)); \
494  if (_old_rt_tree_array) \
495  bu_free((void *)(_old_rt_tree_array), "rt_tree_array"); \
496  db_free_tree((_old_ntp), &rt_uniresource);
497 
498 
499 #define COMBMEM_CHECK_MAT(_tp, _tree_index, _old_rt_tree_array, _mat, _aetvec, _tvec, _svec, _key_pt, _az, _el, _tw, _tx, _ty, _tz, _sa, _sx, _sy, _sz) \
500  bn_mat_mul((_tp)->tr_l.tl_mat, (_mat), (_old_rt_tree_array)[(_tree_index)].tl_tree->tr_l.tl_mat); \
501  \
502 /* If bn_mat_ck fails, it's because scaleX, scaleY and/or scaleZ has been \
503  * been applied along with rotations. This screws up perpendicularity. \
504  */ \
505  if (bn_mat_ck("combmem_set", (_tp)->tr_l.tl_mat)) { \
506  combmem_assemble_mat((_mat), (_aetvec), (_tvec), (_svec), (_key_pt), 0); \
507  bn_mat_mul((_tp)->tr_l.tl_mat, (_mat), (_old_rt_tree_array)[(_tree_index)].tl_tree->tr_l.tl_mat); \
508  \
509  if (bn_mat_ck("combmem_set", (_tp)->tr_l.tl_mat)) { \
510  MAT_COPY((_tp)->tr_l.tl_mat, (_old_rt_tree_array)[(_tree_index)].tl_tree->tr_l.tl_mat); \
511  } \
512  } else { \
513  /* This will check if the 3x3 rotation part is bad after factoring out scaleX, scaleY and scaleZ. */ \
514  if (combmem_disassemble_mat((_tp)->tr_l.tl_mat, &(_az), &(_el), &(_tw), &(_tx), &(_ty), &(_tz), &(_sa), &(_sx), &(_sy), &(_sz))) { \
515  MAT_COPY((_tp)->tr_l.tl_mat, (_old_rt_tree_array)[(_tree_index)].tl_tree->tr_l.tl_mat); \
516  } \
517  }
518 
519 
520 HIDDEN int
521 combmem_set(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
522 {
523  struct rt_db_internal old_intern;
524  union tree *old_ntp;
525  struct rt_tree_array *old_rt_tree_array;
526  size_t old_node_count;
527 
528  struct directory *dp;
529  struct rt_db_internal intern;
530  struct rt_comb_internal *comb;
532  size_t i;
533  size_t node_count;
534  size_t tree_index;
535  union tree *tp;
536  union tree *final_tree;
537 
538  switch (etype) {
539  case ETYPES_ABS:
540  case ETYPES_REL:
541  break;
542  default:
543  return GED_ERROR;
544  }
545 
546  COMBMEM_GETCOMBTREE(gedp, argv[0], argv[1], dp, old_intern, old_ntp, old_rt_tree_array, old_node_count);
547  COMBMEM_SET_PART_I(gedp, argc, argv[0], argv[1], 15, intern, dp, comb, node_count, rt_tree_array);
548 
549  tree_index = 0;
550  for (i = 2; i < (size_t)argc; i += 15) {
551  mat_t mat;
552  double az, el, tw;
553  double tx, ty, tz;
554  double sa, sx, sy, sz;
555  double kx, ky, kz;
556  hvect_t svec = HINIT_ZERO;
557  point_t key_pt = VINIT_ZERO;
558  vect_t aetvec = VINIT_ZERO;
559  vect_t tvec = VINIT_ZERO;
560 
561  COMBMEM_SET_PART_II(gedp, argv[i], rt_tree_array[tree_index], mat);
562 
563  if (sscanf(argv[i+2], "%lf", &az) == 1 &&
564  sscanf(argv[i+3], "%lf", &el) == 1 &&
565  sscanf(argv[i+4], "%lf", &tw) == 1 &&
566  sscanf(argv[i+5], "%lf", &tx) == 1 &&
567  sscanf(argv[i+6], "%lf", &ty) == 1 &&
568  sscanf(argv[i+7], "%lf", &tz) == 1 &&
569  sscanf(argv[i+8], "%lf", &sa) == 1 &&
570  sscanf(argv[i+9], "%lf", &sx) == 1 &&
571  sscanf(argv[i+10], "%lf", &sy) == 1 &&
572  sscanf(argv[i+11], "%lf", &sz) == 1 &&
573  sscanf(argv[i+12], "%lf", &kx) == 1 &&
574  sscanf(argv[i+13], "%lf", &ky) == 1 &&
575  sscanf(argv[i+14], "%lf", &kz) == 1) {
576 
577  VSET(aetvec, az, el, tw);
578  VSCALE(aetvec, aetvec, DEG2RAD);
579  VSET(tvec, tx, ty, tz);
580  VSCALE(tvec, tvec, gedp->ged_wdbp->dbip->dbi_local2base);
581  VSET(key_pt, kx, ky, kz);
582  VSCALE(key_pt, key_pt, gedp->ged_wdbp->dbip->dbi_local2base);
583  QSET(svec, sx, sy, sz, sa);
584 
585  combmem_assemble_mat(mat, aetvec, tvec, svec, key_pt, 1);
586 
587  /* If bn_mat_ck fails, it's because scaleX, scaleY and/or scaleZ has been
588  * been applied along with rotations. This screws up perpendicularity.
589  */
590  if (bn_mat_ck("combmem_set", mat)) {
591  combmem_assemble_mat(mat, aetvec, tvec, svec, key_pt, 0);
592  }
593  }
594 
595  BU_ALLOC(tp, union tree);
596  RT_TREE_INIT(tp);
597  COMBMEM_SET_PART_III(tp, tree, rt_tree_array[tree_index], argv[i+1]);
598 
599  if (etype == ETYPES_REL
600  && tree_index < old_node_count
601  && old_rt_tree_array[tree_index].tl_tree->tr_l.tl_mat
602  && BU_STR_EQUAL(old_rt_tree_array[tree_index].tl_tree->tr_l.tl_name, tp->tr_l.tl_name))
603  {
604  fastf_t azf = az, elf = el, twf = tw;
605  fastf_t txf = tx, tyf = ty, tzf = tz;
606  fastf_t saf = sa, sxf = sx, syf = sy, szf = sz;
607 
608  COMBMEM_CHECK_MAT(tp, tree_index, old_rt_tree_array, mat, aetvec, tvec, svec, key_pt, azf, elf, twf, txf, tyf, tzf, saf, sxf, syf, szf);
609  } else {
610  MAT_COPY(tp->tr_l.tl_mat, mat);
611  }
612 
613  tree_index++;
614  }
615 
616  COMBMEM_SET_PART_IV(gedp, comb, tree_index, intern, final_tree, node_count, dp, rt_tree_array, old_intern, old_rt_tree_array, old_ntp);
617 
618  return GED_OK;
619 }
620 
621 
622 HIDDEN int
623 combmem_set_rot(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
624 {
625  struct rt_db_internal old_intern;
626  union tree *old_ntp;
627  struct rt_tree_array *old_rt_tree_array;
628  size_t old_node_count;
629 
630  struct directory *dp;
631  struct rt_db_internal intern;
632  struct rt_comb_internal *comb;
634  size_t i;
635  size_t node_count;
636  size_t tree_index;
637  union tree *tp;
638  union tree *final_tree;
639 
640  switch (etype) {
641  case ETYPES_ROT_AET:
642  case ETYPES_ROT_XYZ:
643  break;
644  default:
645  return GED_ERROR;
646  }
647 
648  COMBMEM_GETCOMBTREE(gedp, argv[0], argv[1], dp, old_intern, old_ntp, old_rt_tree_array, old_node_count);
649  COMBMEM_SET_PART_I(gedp, argc, argv[0], argv[1], 8, intern, dp, comb, node_count, rt_tree_array);
650 
651  tree_index = 0;
652  for (i = 2; i < (size_t)argc; i += 8) {
653  mat_t mat;
654  double az, el, tw;
655  double kx, ky, kz;
656  point_t key_pt = VINIT_ZERO;
657 
658  COMBMEM_SET_PART_II(gedp, argv[i], rt_tree_array[tree_index], mat);
659 
660  if (sscanf(argv[i+2], "%lf", &az) == 1 &&
661  sscanf(argv[i+3], "%lf", &el) == 1 &&
662  sscanf(argv[i+4], "%lf", &tw) == 1 &&
663  sscanf(argv[i+5], "%lf", &kx) == 1 &&
664  sscanf(argv[i+6], "%lf", &ky) == 1 &&
665  sscanf(argv[i+7], "%lf", &kz) == 1) {
666 
667  mat_t mat_rot;
668 
669  VSET(key_pt, kx, ky, kz);
670  VSCALE(key_pt, key_pt, gedp->ged_wdbp->dbip->dbi_local2base);
671 
672  if (etype == ETYPES_ROT_AET) {
673  az *= DEG2RAD;
674  el *= DEG2RAD;
675  tw *= DEG2RAD;
676  combmem_mat_aet(mat_rot, az, el, tw);
677  } else
678  bn_mat_angles(mat_rot, az, el, tw);
679 
680  bn_mat_xform_about_pt(mat, mat_rot, key_pt);
681  }
682 
683  BU_ALLOC(tp, union tree);
684  RT_TREE_INIT(tp);
685  COMBMEM_SET_PART_III(tp, tree, rt_tree_array[tree_index], argv[i+1]);
686 
687  if (tree_index < old_node_count
688  && old_rt_tree_array[tree_index].tl_tree->tr_l.tl_mat
689  && BU_STR_EQUAL(old_rt_tree_array[tree_index].tl_tree->tr_l.tl_name, tp->tr_l.tl_name))
690  {
691  fastf_t azf = az, elf = el, twf = tw;
692  fastf_t tx, ty, tz;
693  fastf_t sa, sx, sy, sz;
694  hvect_t svec = HINIT_ZERO;
695  vect_t aetvec = VINIT_ZERO;
696  vect_t tvec = VINIT_ZERO;
697 
698  COMBMEM_CHECK_MAT(tp, tree_index, old_rt_tree_array, mat, aetvec, tvec, svec, key_pt, azf, elf, twf, tx, ty, tz, sa, sx, sy, sz);
699  } else {
700  MAT_COPY(tp->tr_l.tl_mat, mat);
701  }
702 
703  tree_index++;
704  }
705 
706  COMBMEM_SET_PART_IV(gedp, comb, tree_index, intern, final_tree, node_count, dp, rt_tree_array, old_intern, old_rt_tree_array, old_ntp);
707 
708  return GED_OK;
709 }
710 
711 
712 HIDDEN int
713 combmem_set_arb_rot(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
714 {
715  struct rt_db_internal old_intern;
716  union tree *old_ntp;
717  struct rt_tree_array *old_rt_tree_array;
718  size_t old_node_count;
719 
720  struct directory *dp;
721  struct rt_db_internal intern;
722  struct rt_comb_internal *comb;
724  size_t i;
725  size_t node_count;
726  size_t tree_index;
727  union tree *tp;
728  union tree *final_tree;
729 
730  if (etype != ETYPES_ROT_ARBITRARY_AXIS)
731  return GED_ERROR;
732 
733  COMBMEM_GETCOMBTREE(gedp, argv[0], argv[1], dp, old_intern, old_ntp, old_rt_tree_array, old_node_count);
734  COMBMEM_SET_PART_I(gedp, argc, argv[0], argv[1], 9, intern, dp, comb, node_count, rt_tree_array);
735 
736  tree_index = 0;
737  for (i = 2; i < (size_t)argc; i += 9) {
738  mat_t mat;
739  double px, py, pz;
740  double dx, dy, dz;
741  double ang;
742  vect_t dir;
743  point_t pt;
744 
745  COMBMEM_SET_PART_II(gedp, argv[i], rt_tree_array[tree_index], mat);
746 
747  if (sscanf(argv[i+2], "%lf", &px) == 1 &&
748  sscanf(argv[i+3], "%lf", &py) == 1 &&
749  sscanf(argv[i+4], "%lf", &pz) == 1 &&
750  sscanf(argv[i+5], "%lf", &dx) == 1 &&
751  sscanf(argv[i+6], "%lf", &dy) == 1 &&
752  sscanf(argv[i+7], "%lf", &dz) == 1 &&
753  sscanf(argv[i+8], "%lf", &ang) == 1) {
754 
755  VSET(pt, px, py, pz);
756  VSCALE(pt, pt, gedp->ged_wdbp->dbip->dbi_local2base);
757  VSET(dir, dx, dy, dz);
758  VUNITIZE(dir);
759  ang *= DEG2RAD;
760  bn_mat_arb_rot(mat, pt, dir, ang);
761  }
762 
763  BU_ALLOC(tp, union tree);
764  RT_TREE_INIT(tp);
765  COMBMEM_SET_PART_III(tp, tree, rt_tree_array[tree_index], argv[i+1]);
766 
767  if (tree_index < old_node_count && old_rt_tree_array[tree_index].tl_tree->tr_l.tl_mat &&
768  BU_STR_EQUAL(old_rt_tree_array[tree_index].tl_tree->tr_l.tl_name, tp->tr_l.tl_name)) {
769  fastf_t az, el, tw;
770  fastf_t tx, ty, tz;
771  fastf_t sa, sx, sy, sz;
772  hvect_t svec = HINIT_ZERO;
773  point_t key_pt = VINIT_ZERO;
774  vect_t aetvec = VINIT_ZERO;
775  vect_t tvec = VINIT_ZERO;
776 
777  COMBMEM_CHECK_MAT(tp, tree_index, old_rt_tree_array, mat, aetvec, tvec, svec, key_pt, az, el, tw, tx, ty, tz, sa, sx, sy, sz);
778  } else {
779  MAT_COPY(tp->tr_l.tl_mat, mat);
780  }
781 
782  tree_index++;
783  }
784 
785  COMBMEM_SET_PART_IV(gedp, comb, tree_index, intern, final_tree, node_count, dp, rt_tree_array, old_intern, old_rt_tree_array, old_ntp);
786 
787  return GED_OK;
788 }
789 
790 
791 HIDDEN int
792 combmem_set_tra(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
793 {
794  struct rt_db_internal old_intern;
795  union tree *old_ntp;
796  struct rt_tree_array *old_rt_tree_array;
797  size_t old_node_count;
798 
799  struct directory *dp;
800  struct rt_db_internal intern;
801  struct rt_comb_internal *comb;
803  size_t i;
804  size_t node_count;
805  size_t tree_index;
806  union tree *tp;
807  union tree *final_tree;
808 
809  if (etype != ETYPES_TRA)
810  return GED_ERROR;
811 
812  COMBMEM_GETCOMBTREE(gedp, argv[0], argv[1], dp, old_intern, old_ntp, old_rt_tree_array, old_node_count);
813  COMBMEM_SET_PART_I(gedp, argc, argv[0], argv[1], 5, intern, dp, comb, node_count, rt_tree_array);
814 
815  tree_index = 0;
816  for (i = 2; i < (size_t)argc; i += 5) {
817  mat_t mat;
818  double tx, ty, tz;
819  vect_t tvec = VINIT_ZERO;
820 
821  COMBMEM_SET_PART_II(gedp, argv[i], rt_tree_array[tree_index], mat);
822 
823  if (sscanf(argv[i+2], "%lf", &tx) == 1 &&
824  sscanf(argv[i+3], "%lf", &ty) == 1 &&
825  sscanf(argv[i+4], "%lf", &tz) == 1) {
826 
827  VSET(tvec, tx, ty, tz);
828  VSCALE(tvec, tvec, gedp->ged_wdbp->dbip->dbi_local2base);
829  MAT_DELTAS_VEC(mat, tvec);
830  }
831 
832  BU_ALLOC(tp, union tree);
833  RT_TREE_INIT(tp);
834  COMBMEM_SET_PART_III(tp, tree, rt_tree_array[tree_index], argv[i+1]);
835 
836  if (tree_index < old_node_count && old_rt_tree_array[tree_index].tl_tree->tr_l.tl_mat &&
837  BU_STR_EQUAL(old_rt_tree_array[tree_index].tl_tree->tr_l.tl_name, tp->tr_l.tl_name)) {
838 
839  bn_mat_mul(tp->tr_l.tl_mat, mat, old_rt_tree_array[tree_index].tl_tree->tr_l.tl_mat);
840  } else {
841  MAT_COPY(tp->tr_l.tl_mat, mat);
842  }
843 
844  tree_index++;
845  }
846 
847  COMBMEM_SET_PART_IV(gedp, comb, tree_index, intern, final_tree, node_count, dp, rt_tree_array, old_intern, old_rt_tree_array, old_ntp);
848 
849  return GED_OK;
850 }
851 
852 
853 HIDDEN int
854 combmem_set_sca(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
855 {
856  struct rt_db_internal old_intern;
857  union tree *old_ntp;
858  struct rt_tree_array *old_rt_tree_array;
859  size_t old_node_count;
860 
861  struct directory *dp;
862  struct rt_db_internal intern;
863  struct rt_comb_internal *comb;
865  size_t i;
866  size_t node_count;
867  size_t tree_index;
868  union tree *tp;
869  union tree *final_tree;
870 
871  if (etype != ETYPES_SCA)
872  return GED_ERROR;
873 
874  COMBMEM_GETCOMBTREE(gedp, argv[0], argv[1], dp, old_intern, old_ntp, old_rt_tree_array, old_node_count);
875  COMBMEM_SET_PART_I(gedp, argc, argv[0], argv[1], 9, intern, dp, comb, node_count, rt_tree_array);
876 
877  tree_index = 0;
878  for (i = 2; i < (size_t)argc; i += 9) {
879  mat_t mat;
880  double sa, sx, sy, sz;
881  double kx, ky, kz;
882  hvect_t svec = HINIT_ZERO;
883  point_t key_pt = VINIT_ZERO;
884  vect_t aetvec = VINIT_ZERO;
885  vect_t tvec = VINIT_ZERO;
886 
887  HSETALL(svec, 0);
888 
889  COMBMEM_SET_PART_II(gedp, argv[i], rt_tree_array[tree_index], mat);
890 
891  if (sscanf(argv[i+2], "%lf", &sa) == 1 &&
892  sscanf(argv[i+3], "%lf", &sx) == 1 &&
893  sscanf(argv[i+4], "%lf", &sy) == 1 &&
894  sscanf(argv[i+5], "%lf", &sz) == 1 &&
895  sscanf(argv[i+6], "%lf", &kx) == 1 &&
896  sscanf(argv[i+7], "%lf", &ky) == 1 &&
897  sscanf(argv[i+8], "%lf", &kz) == 1) {
898 
899  VSETALL(aetvec, 0.0);
900  VSETALL(tvec, 0.0);
901  VSET(key_pt, kx, ky, kz);
902  VSCALE(key_pt, key_pt, gedp->ged_wdbp->dbip->dbi_local2base);
903  QSET(svec, sx, sy, sz, sa);
904 
905  combmem_assemble_mat(mat, aetvec, tvec, svec, key_pt, 1);
906  }
907 
908  BU_ALLOC(tp, union tree);
909  RT_TREE_INIT(tp);
910  COMBMEM_SET_PART_III(tp, tree, rt_tree_array[tree_index], argv[i+1]);
911 
912  if (tree_index < old_node_count
913  && old_rt_tree_array[tree_index].tl_tree->tr_l.tl_mat
914  && BU_STR_EQUAL(old_rt_tree_array[tree_index].tl_tree->tr_l.tl_name, tp->tr_l.tl_name))
915  {
916  fastf_t az, el, tw;
917  fastf_t tx, ty, tz;
918  fastf_t saf = sa, sxf = sx, syf = sy, szf = sz;
919 
920  COMBMEM_CHECK_MAT(tp, tree_index, old_rt_tree_array, mat, aetvec, tvec, svec, key_pt, az, el, tw, tx, ty, tz, saf, sxf, syf, szf);
921  } else {
922  MAT_COPY(tp->tr_l.tl_mat, mat);
923  }
924 
925  tree_index++;
926  }
927 
928  COMBMEM_SET_PART_IV(gedp, comb, tree_index, intern, final_tree, node_count, dp, rt_tree_array, old_intern, old_rt_tree_array, old_ntp);
929 
930  return GED_OK;
931 }
932 
933 
934 HIDDEN int
935 combmem_set_empty(struct ged *gedp, int argc, const char *argv[])
936 {
937  struct directory *dp;
938  struct rt_comb_internal *comb;
939  struct rt_db_internal intern;
940 
941  if (argc < 2) {
942  bu_vls_printf(gedp->ged_result_str, "ERROR argument missing after [%s]\n", argv[0]);
943  return GED_ERROR;
944  }
945 
946  if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_NOISY)) == RT_DIR_NULL) {
947  bu_vls_printf(gedp->ged_result_str, "%s: Warning - %s not found in database.\n", argv[0], argv[1]);
948  return GED_ERROR;
949  }
950 
951  if (!(dp->d_flags & RT_DIR_COMB)) {
952  bu_vls_printf(gedp->ged_result_str, "%s: Warning - %s not a combination\n", argv[0], argv[1]);
953  return GED_ERROR;
954  } \
955 
956  if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (matp_t)NULL, &rt_uniresource) < 0) {
957  bu_vls_printf(gedp->ged_result_str, "Database read error, aborting");
958  return GED_ERROR;
959  }
960  comb = (struct rt_comb_internal *)intern.idb_ptr;
961  RT_CK_COMB(comb);
962 
964  comb->tree = NULL;
965 
966  if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) {
967  bu_vls_printf(gedp->ged_result_str, "Unable to write combination into database - %s\n", argv[1]);
968  return GED_ERROR;
969  }
970 
971  return GED_OK;
972 }
973 
974 
975 /*
976  * Set/get a combinations members.
977  */
978 int
979 ged_combmem(struct ged *gedp, int argc, const char *argv[])
980 {
981  int c;
982  enum etypes iflag = ETYPES_ABS;
983  enum etypes rflag = ETYPES_NULL;
984  const char *cmd_name = argv[0];
985  static const char *usage = "[-i type] [-r type] comb [op1 name1 az1 el1 tw1 x1 y1 z1 sa1 sx1 sy1 sz1 ...]";
986 
987  /* initialize result */
988  bu_vls_trunc(gedp->ged_result_str, 0);
989 
990  /* must be wanting help */
991  if (argc == 1) {
992  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", cmd_name, usage);
993  return GED_HELP;
994  }
995 
996  bu_optind = 1;
997 
998  /* Get command line options. */
999  while ((c = bu_getopt(argc, (char * const *)argv, "i:r:")) != -1) {
1000  switch (c) {
1001  case 'i':
1002  {
1003  int d;
1004 
1005  if (sscanf(bu_optarg, "%d", &d) != 1 || d < ETYPES_ABS || d > ETYPES_SCA) {
1006  goto bad;
1007  }
1008 
1009  iflag = (enum etypes)d;
1010  }
1011  break;
1012  case 'r':
1013  {
1014  int d;
1015 
1016  if (sscanf(bu_optarg, "%d", &d) != 1 || d < ETYPES_ABS || d > ETYPES_SCA) {
1017  goto bad;
1018  }
1019 
1020  rflag = (enum etypes)d;
1021  }
1022  break;
1023  default:
1024  break;
1025  }
1026  }
1027  argc -= (bu_optind - 1);
1028  argv += (bu_optind - 1);
1029 
1030  if (argc == 2) {
1031  if (rflag == ETYPES_NULL)
1032  return combmem_get(gedp, argc, argv, iflag);
1033 
1034  /* Remove all members */
1035  return combmem_set_empty(gedp, argc, argv);
1036  }
1037 
1038  /* Check number of args */
1039  switch (rflag) {
1040  case ETYPES_ABS:
1041  case ETYPES_REL:
1042  if (argc > 16 && !((argc-2)%15)) {
1043  return combmem_set(gedp, argc, argv, rflag);
1044  }
1045  break;
1046  case ETYPES_ROT_AET:
1047  case ETYPES_ROT_XYZ:
1048  if (argc > 9 && !((argc-2)%8)) {
1049  return combmem_set_rot(gedp, argc, argv, rflag);
1050  }
1051  break;
1053  if (argc > 10 && !((argc-2)%9)) {
1054  return combmem_set_arb_rot(gedp, argc, argv, rflag);
1055  }
1056  break;
1057  case ETYPES_TRA:
1058  if (argc > 6 && !((argc-2)%5)) {
1059  return combmem_set_tra(gedp, argc, argv, rflag);
1060  }
1061  break;
1062  case ETYPES_SCA:
1063  if (argc > 10 && !((argc-2)%9)) {
1064  return combmem_set_sca(gedp, argc, argv, rflag);
1065  }
1066  break;
1067  case ETYPES_NULL:
1068  default:
1069  if (argc > 16 && !((argc-2)%15)) {
1070  return combmem_set(gedp, argc, argv, ETYPES_ABS);
1071  }
1072  break;
1073  }
1074 
1075 bad:
1076  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", cmd_name, usage);
1077  return GED_ERROR;
1078 }
1079 
1080 
1081 /*
1082  * Local Variables:
1083  * tab-width: 8
1084  * mode: C
1085  * indent-tabs-mode: t
1086  * c-file-style: "stroustrup"
1087  * End:
1088  * ex: shiftwidth=4 tabstop=8
1089  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
HIDDEN int combmem_set_empty(struct ged *gedp, int argc, const char *argv[])
Definition: combmem.c:935
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 rt_db_put_internal(struct directory *dp, struct db_i *dbip, struct rt_db_internal *ip, struct resource *resp)
Definition: dir.c:136
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
#define VSET(a, b, c, d)
Definition: color.c:53
#define VSETALL(a, s)
Definition: color.c:54
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
#define BU_ASSERT_LONG(_lhs, _relation, _rhs)
Definition: defines.h:240
#define COMBMEM_SET_PART_I(_gedp, _argc, _cmd, _name, _num_params, _intern, _dp, _comb, _node_count, _rt_tree_array)
Definition: combmem.c:420
HIDDEN int combmem_set_rot(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
Definition: combmem.c:623
#define RT_CK_COMB(_p)
Definition: raytrace.h:955
union tree * tl_tree
Definition: raytrace.h:1247
#define COMBMEM_SET_PART_III(_tp, _tree, _rt_tree_array_index, _name)
Definition: combmem.c:459
struct rt_wdb * ged_wdbp
Definition: ged.h:340
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
HIDDEN int combmem_set_tra(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
Definition: combmem.c:792
#define GED_ERROR
Definition: ged.h:61
#define HIDDEN
Definition: common.h:86
#define RT_TREE_INIT(_p)
Definition: raytrace.h:1189
HIDDEN void combmem_mat_aet(matp_t matp, fastf_t az, fastf_t el, fastf_t tw)
Definition: combmem.c:52
if(share_geom)
Definition: nmg_mod.c:3829
#define OP_SUBTRACT
Binary: L subtract R.
Definition: raytrace.h:1129
Definition: color.c:49
HIDDEN void combmem_disassemble_rmat(matp_t matp, fastf_t *az, fastf_t *el, fastf_t *tw)
Definition: combmem.c:93
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 OP_DB_LEAF
Leaf of combination, db fmt.
Definition: raytrace.h:1139
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
HIDDEN int combmem_disassemble_mat(matp_t matp, fastf_t *az, fastf_t *el, fastf_t *tw, fastf_t *tx, fastf_t *ty, fastf_t *tz, fastf_t *sa, fastf_t *sx, fastf_t *sy, fastf_t *sz)
Definition: combmem.c:145
#define COMBMEM_CHECK_MAT(_tp, _tree_index, _old_rt_tree_array, _mat, _aetvec, _tvec, _svec, _key_pt, _az, _el, _tw, _tx, _ty, _tz, _sa, _sx, _sy, _sz)
Definition: combmem.c:499
int ged_combmem(struct ged *gedp, int argc, const char *argv[])
Definition: combmem.c:979
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
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
HIDDEN int combmem_set(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
Definition: combmem.c:521
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
int bn_mat_ck(const char *title, const mat_t m)
Definition: mat.c:1058
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
HIDDEN void combmem_assemble_mat(matp_t matp, vect_t aetvec, vect_t tvec, hvect_t svec, point_t key_pt, int sflag)
Definition: combmem.c:208
#define COMBMEM_GETCOMBTREE(_gedp, _cmd, _name, _dp, _intern, _ntp, _rt_tree_array, _node_count)
Definition: combmem.c:326
struct bu_vls * ged_result_str
Definition: ged.h:357
void bn_mat_angles(mat_t mat, double alpha, double beta, double ggamma)
struct tree::tree_db_leaf tr_l
#define ZERO(val)
Definition: units.c:38
void * idb_ptr
Definition: raytrace.h:195
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
Definition: op.h:35
#define BU_ASSERT_PTR(_lhs, _relation, _rhs)
Definition: defines.h:227
HIDDEN int combmem_set_sca(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
Definition: combmem.c:854
HIDDEN void combmem_vls_print_member_info(struct ged *gedp, char op, union tree *itp, enum etypes etype)
Definition: combmem.c:271
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
#define COMBMEM_SET_PART_II(_gedp, _opstr, _rt_tree_array_index, _mat)
Definition: combmem.c:437
#define COMBMEM_SET_PART_IV(_gedp, _comb, _tree_index, _intern, _final_tree, _node_count, _dp, _rt_tree_array, _old_intern, _old_rt_tree_array, _old_ntp)
Definition: combmem.c:466
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
#define GED_HELP
Definition: ged.h:62
Definition: color.c:51
etypes
Definition: combmem.c:35
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
HIDDEN int combmem_get(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
Definition: combmem.c:371
#define RT_CK_TREE(_p)
Definition: raytrace.h:1182
double dbi_local2base
local2mm
Definition: raytrace.h:807
void bn_mat_xform_about_pt(mat_t mat, const mat_t xform, const point_t pt)
Definition: mat.c:909
int d_flags
flags
Definition: raytrace.h:869
HIDDEN int combmem_set_arb_rot(struct ged *gedp, int argc, const char *argv[], enum etypes etype)
Definition: combmem.c:713
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
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
void bn_mat_arb_rot(mat_t m, const point_t pt, const vect_t dir, const fastf_t ang)
Definition: mat.c:987
Definition: color.c:50
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126