BRL-CAD
pull.c
Go to the documentation of this file.
1 /* P U L L . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2013-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/push.c
21  * The pull command.
22  * This is the Pull command which pulls the matrix transformations of an object
23  * up the CSG Tree.
24  */
25 
26 
27 #include "common.h"
28 
29 #include <stdlib.h>
30 #include <string.h>
31 
32 
33 #include "bu/cmd.h"
34 #include "bu/getopt.h"
35 #include "bn.h"
36 
37 #include "./ged_private.h"
38 
39 
40 void
41 pull_comb(struct db_i *dbip,
42  struct directory *dp,
43  void *mp);
44 
45 
46 /* This restores the matrix transformation at a combination by taking leaf matrix transformations, inverting
47  * and storing the changes at the combinations.
48  */
49 static void
50 pull_comb_mat(struct db_i *dbip, struct rt_comb_internal *UNUSED(comb), union tree *comb_leaf, void *mp, void *UNUSED(usr_ptr2),
51  void *UNUSED(usr_ptr3), void *UNUSED(usr_ptr4))
52 {
53  struct directory *dp;
54  mat_t inv_mat;
55  matp_t mat = (matp_t)mp;
56 
57  RT_CK_DBI(dbip);
58  RT_CK_TREE(comb_leaf);
59 
60  if ((dp = db_lookup(dbip, comb_leaf->tr_l.tl_name, LOOKUP_NOISY)) == RT_DIR_NULL)
61  return;
62 
63  if (!comb_leaf->tr_l.tl_mat) {
64  comb_leaf->tr_l.tl_mat = (matp_t)bu_malloc(sizeof(mat_t), "tl_mat");
65  MAT_COPY(comb_leaf->tr_l.tl_mat, mat);
66 
67  return;
68  }
69 
70  /* invert the matrix transformation of the leaf and store new matrix at comb */
71  bn_mat_inverse(inv_mat, comb_leaf->tr_l.tl_mat );
72 
73  /* multiply inverse and store at combination */
74  bn_mat_mul2(inv_mat,mat);
75  MAT_COPY(comb_leaf->tr_l.tl_mat, mat);
76  pull_comb(dbip, dp, mp);
77 }
78 
79 
80 /* pull_comb(): This routine enters a comb restoring the matrix transformation at the combination
81  * calls and calls pull_comb_mat() which updates current matrix transformation and moves up tree.
82  * Note: the generic pointer points to a matrix if successful or a string if unsuccessful.
83  */
84 void
85 pull_comb(struct db_i *dbip,
86  struct directory *dp,
87  void *mp)
88 {
89  struct rt_db_internal intern;
90  struct rt_comb_internal *comb;
91  matp_t mat = (matp_t)mp;
92  mat_t m;
93  mat_t invMat;
94 
95  if (dp->d_flags & RT_DIR_SOLID)
96  return;
97  if (rt_db_get_internal(&intern, dp, dbip, m, &rt_uniresource) < 0) {
98  bu_log("Database read error, aborting\n");
99  return;
100  }
101 
102  comb = (struct rt_comb_internal *)intern.idb_ptr;
103 
104  /* checks if matrix pointer is valid */
105  if (mat == NULL) {
106  mat = (matp_t)bu_malloc(sizeof(mat_t), "cur_mat");
107  MAT_IDN(mat);
108  }
109 
110  bn_mat_inverse(invMat, mat);
111  bn_mat_mul2(mat,m);
112  MAT_COPY(mat, m);/* updates current matrix pointer */
113 
114  if (comb->tree) {
115  db_tree_funcleaf(dbip, comb, comb->tree, pull_comb_mat,
116  &m, (void *)NULL, (void *)NULL, (void *)NULL);
117 
118  if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource) < 0) {
119  bu_log("Cannot write modified combination (%s) to database\n", dp->d_namep);
120  return;
121  }
122  }
123 }
124 
125 
126 /* routine takes the maximum and minimum points from the AABB and determines the translation matrix
127  * which moves the centrepoint to the origin and moves the primitive by its inverse
128  * before pulling the translation.
129  */
130 void
131 translate(matp_t matrix, mat_t tm, point_t min, point_t max)
132 {
133  vect_t c_pt = VINIT_ZERO; /* centre point */
134  mat_t t_mat = MAT_INIT_ZERO; /* temp matrix */
135  vect_t t_vec = VINIT_ZERO; /* translation vector */
136 
137  /* computes the centrepoint from both minimum and maximum point
138  * following this algorithm: cen[i] = bbx_min[i] + bbx_max[i]) / 2.0
139  */
140  VADD2(c_pt, max, min);
141  VSCALE(c_pt, c_pt, 1/2);
142 
143  /* translates the centrepoint to the origin. and computes the inverse of this transformation which will be applied to the primitive */
144  VREVERSE(t_vec, c_pt);
145  MAT_DELTAS_VEC(t_mat, t_vec);
146  MAT_DELTAS_VEC(matrix, t_vec);/* pulls translation component of primitive */
147 
148  /* copies transformation matrix whose inverse restores primitive and bbox */
149  MAT_COPY(tm, t_mat);
150 
151  return;
152 }
153 
154 
155 /**
156  * @brief
157  * This routine takes the internal database representation of a leaf node or
158  * primitive object and builds a matrix transformation, closest to this node's,
159  * sets these values to default and returns matrix.
160  * Fixme: This routine only pulls translations up. So additional support for rotations/scale
161  * would be needed for further purposes.
162  */
163 static void
164 pull_leaf(struct db_i *dbip, struct directory *dp, void *mp)
165 {
166  struct rt_db_internal intern;
167  struct bn_tol tol;
168  point_t min; /* minimum point of bbox */
169  point_t max; /* maximum point of bbox */
170  matp_t mat = (matp_t)mp; /* current transformation matrix */
171  mat_t matrix, invXform;
172 
173  BN_TOL_INIT(&tol); /* initializes the tolerance */
174 
175  if (mat == NULL) {
176  mat = (matp_t)bu_malloc(sizeof(mat_t), "cur_mat");
177  MAT_IDN(mat);
178  }
179 
180  if (!(dp->d_flags & RT_DIR_SOLID))
181  return;
182  if (rt_db_get_internal(&intern, dp, dbip, mat, &rt_uniresource) < 0) {
183  bu_vls_printf((struct bu_vls *)mp, "Database read error, aborting\n");
184  return;
185  }
186 
187  MAT_IDN(mat);
188  MAT_IDN(matrix);
189 
190  /* this computes the AABB bounding box of the leaf object
191  * using the bbox call back routine in its rt_functab table.
192  * it then passes the minimum and maximum point to translate()
193  * which then extracts the translation.
194  */
195  (intern.idb_meth)->ft_bbox(&intern, &min, &max, &tol);
196 
197  /* pulls primitive translation matrix copying inverse transformation to restore primitive and bbox */
198  translate(mat,matrix, min, max);
199  bn_mat_inverse(invXform, matrix);/* computes the inverse of transformation matrix. */
200 
201  (intern.idb_meth)->ft_xform(&intern, invXform, &intern, 0, dbip, &rt_uniresource);/* restores the primitive */
202 
203  return;
204 }
205 
206 
207 int
208 ged_pull(struct ged *gedp, int argc, const char *argv[])
209 {
210  struct directory *dp;
211  mat_t mat;
212  int c;
213  static const char *usage = "object";
214 
217  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
218 
219  /* initialize result */
220  bu_vls_trunc(gedp->ged_result_str, 0);
221 
222  /* must be wanting help */
223  if (argc == 1) {
224  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
225  return GED_HELP;
226  }
227 
228  if (argc != 2) {
229  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
230  return GED_ERROR;
231  }
232 
233  /* get directory pointer for arg */
234  if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[1], LOOKUP_NOISY)) == RT_DIR_NULL)
235  return GED_ERROR;
236 
237  /* Checks whether the object is a primitive.*/
238  if (dp->d_flags & RT_DIR_SOLID) {
239  bu_log("Attempt to pull primitive, aborting.\n");
240  return GED_ERROR;
241  }
242 
243  /* Parse options */
244  bu_optind = 1; /* re-init bu_getopt() */
245  while ((c = bu_getopt(argc, (char * const *)argv, "d")) != -1) {
246  switch (c) {
247  case 'd':
249  break;
250  case '?':
251  default:
252  bu_vls_printf(gedp->ged_result_str, "ged_pull: usage pull [-d] root \n");
253  break;
254  }
255  }
256 
257  /*
258  * uses a no frills walk routine recursively moving up the tree
259  * from the leaves performing the necessary matrix transformations moving up
260  * right to the the head of the tree pulling objects.
261  * All new changes are immediately written to database
262  */
263  db_functree(gedp->ged_wdbp->dbip, dp, pull_comb, pull_leaf, &rt_uniresource, &mat);
264 
265  return GED_OK;
266 }
267 
268 
269 /** @} */
270 /*
271  * Local Variables:
272  * mode: C
273  * tab-width: 8
274  * indent-tabs-mode: t
275  * c-file-style: "stroustrup"
276  * End:
277  * ex: shiftwidth=4 tabstop=8
278  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
char * d_namep
pointer to name string
Definition: raytrace.h:859
#define BN_TOL_INIT(_p)
Definition: tol.h:87
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 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
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
void pull_comb(struct db_i *dbip, struct directory *dp, void *mp)
Definition: pull.c:85
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
int bn_mat_inverse(mat_t output, const mat_t input)
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
#define GED_ERROR
Definition: ged.h:61
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
void bn_mat_mul2(const mat_t i, mat_t o)
if(share_geom)
Definition: nmg_mod.c:3829
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
#define RT_DIR_SOLID
this name is a solid
Definition: raytrace.h:883
matp_t tl_mat
xform matp, NULL ==> identity
Definition: raytrace.h:1173
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
#define UNUSED(parameter)
Definition: common.h:239
Support for uniform tolerances.
Definition: tol.h:71
int ged_pull(struct ged *gedp, int argc, const char *argv[])
Definition: pull.c:208
struct bu_vls * ged_result_str
Definition: ged.h:357
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
struct tree::tree_db_leaf tr_l
void * idb_ptr
Definition: raytrace.h:195
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define RT_DIR_NULL
Definition: raytrace.h:875
#define LOOKUP_NOISY
Definition: raytrace.h:892
#define GED_HELP
Definition: ged.h:62
uint32_t debug
!0 for debug, see librt/debug.h
Definition: raytrace.h:1695
void db_functree(struct db_i *dbip, struct directory *dp, void(*comb_func)(struct db_i *, struct directory *, void *), void(*leaf_func)(struct db_i *, struct directory *, void *), struct resource *resp, void *client_data)
Definition: db_walk.c:199
void db_tree_funcleaf(struct db_i *dbip, struct rt_comb_internal *comb, union tree *comb_tree, void(*leaf_func)(struct db_i *, struct rt_comb_internal *, union tree *, void *, void *, void *, void *), void *user_ptr1, void *user_ptr2, void *user_ptr3, void *user_ptr4)
Definition: db_tree.c:640
#define RT_CK_TREE(_p)
Definition: raytrace.h:1182
#define DEBUG_TREEWALK
22 Database tree traversal
Definition: raytrace.h:107
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int d_flags
flags
Definition: raytrace.h:869
Definition: vls.h:56
void translate(matp_t matrix, mat_t tm, point_t min, point_t max)
Definition: pull.c:131
struct rt_g RTG
Definition: globals.c:39