BRL-CAD
bb.c
Go to the documentation of this file.
1 /* B B . 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/bb.c
21  *
22  * The bb command - report the dimensions of the bounding arb8
23  * for a given object and optionally create an arb8 with those
24  * dimensions.
25  *
26  */
27 
28 #include "common.h"
29 
30 #include <string.h>
31 
32 #include "bu/cmd.h"
33 #include "bu/getopt.h"
34 #include "bu/units.h"
35 #include "rtgeom.h"
36 
37 #include "./ged_private.h"
38 
39 
40 int
41 ged_bb(struct ged *gedp, int argc, const char *argv[])
42 {
43  point_t rpp_min, rpp_max;
44  point_t obj_min, obj_max;
45  int c;
46  int use_air = 1;
47  int print_header = 1;
48  int print_rpp = 0;
49  int print_dim = 0;
50  int print_vol = 0;
51  int make_bb = 0;
52  int oriented_bb = 0;
53  int i;
54  static const char *usage = "[options] object1 [object2 object3 ...]";
55  const char *str;
56  double xlen;
57  double ylen;
58  double zlen;
59  double vol;
60  double oriented_bbox_tol = BN_TOL_DIST;
61  char bbname[64];
62 
65  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
66 
67  /* initialize result */
68  bu_vls_trunc(gedp->ged_result_str, 0);
69 
70  /* must be wanting help */
71  if (argc == 1) {
72  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
73  return GED_HELP;
74  }
75 
76  bu_optind = 1; /* re-init bu_getopt() */
77  while ((c = bu_getopt(argc, (char * const *)argv, "c:dequvo")) != -1) {
78  switch (c) {
79  case 'c':
80  make_bb = 1;
81  memset(bbname, 0, 64);
82  bu_strlcpy(bbname, bu_optarg, 64);
83  break;
84  case 'd':
85  print_dim = 1;
86  break;
87  case 'e':
88  print_rpp = 1;
89  break;
90  case 'q':
91  print_header = 0;
92  break;
93  case 'u':
94  use_air = 0;
95  break;
96  case 'v':
97  print_vol = 1;
98  break;
99  case 'o':
100  oriented_bb = 1;
101  break;
102  default:
103  bu_vls_printf(gedp->ged_result_str, "Unrecognized option - %c", c);
104  return GED_ERROR;
105  }
106  }
107 
108  /* Don't want to print NO info, so default to dim and vol printout if nothing specified. */
109  if (print_rpp == 0 && print_vol == 0 && print_dim == 0) {
110  print_dim = 1;
111  print_vol = 1;
112  }
113 
114  /* skip options processed plus command name, should just leave object names */
115  argc -= bu_optind;
116  argv += bu_optind;
117 
118  /* must be wanting help */
119  if (argc == 0) {
120  bu_vls_printf(gedp->ged_result_str, "Usage: bb %s", usage);
121  return GED_HELP;
122  }
123 
124  if (!oriented_bb) {
125 
126  VSETALL(rpp_min, INFINITY);
127  VSETALL(rpp_max, -INFINITY);
128  for (i = 0; i < argc; i++) {
129  if (ged_get_obj_bounds(gedp, argc - i, (const char **)argv+i, use_air, obj_min, obj_max) == GED_ERROR)
130  return GED_ERROR;
131  VMINMAX(rpp_min, rpp_max, (double *)obj_min);
132  VMINMAX(rpp_min, rpp_max, (double *)obj_max);
133  }
134 
135  /* Report Bounding Box Information */
137  if (!str) str = "Unknown_unit";
138 
139  /* Print Header */
140  if (print_header == 1) {
141  bu_vls_printf(gedp->ged_result_str, "Bounding Box Dimensions, Object(s)");
142  for (i = 0; i < argc - 1 ; i++) {
143  bu_vls_printf(gedp->ged_result_str, " %s, ", argv[i]);
144  }
145  bu_vls_printf(gedp->ged_result_str, " %s:\n", argv[argc-1]);
146  }
147 
148  /* Print rpp */
149  if (print_rpp == 1) {
150  bu_vls_printf(gedp->ged_result_str, "min {%f %f %f} max {%f %f %f}\n", rpp_min[0], rpp_min[1], rpp_min[2], rpp_max[0], rpp_max[1], rpp_max[2]);
151  }
152 
153  /* Print dim info */
154  if (print_dim == 1) {
155  xlen = fabs(rpp_max[X] - rpp_min[X])*gedp->ged_wdbp->dbip->dbi_base2local;
156  ylen = fabs(rpp_max[Y] - rpp_min[Y])*gedp->ged_wdbp->dbip->dbi_base2local;
157  zlen = fabs(rpp_max[Z] - rpp_min[Z])*gedp->ged_wdbp->dbip->dbi_base2local;
158  bu_vls_printf(gedp->ged_result_str, "X Length: %g %s\nY Length: %g %s\nZ Length: %g %s\n", xlen, str, ylen, str, zlen, str);
159  }
160 
161  if (print_vol == 1) {
162  xlen = fabs(rpp_max[X] - rpp_min[X])*gedp->ged_wdbp->dbip->dbi_base2local;
163  ylen = fabs(rpp_max[Y] - rpp_min[Y])*gedp->ged_wdbp->dbip->dbi_base2local;
164  zlen = fabs(rpp_max[Z] - rpp_min[Z])*gedp->ged_wdbp->dbip->dbi_base2local;
165  vol = xlen * ylen * zlen;
166  bu_vls_printf(gedp->ged_result_str, "Bounding Box Volume: %g %s^3\n", vol, str);
167  }
168 
169  if (make_bb == 1) {
170  struct directory *dp;
171  struct rt_arb_internal *arb;
172  struct rt_db_internal new_intern;
173 
174  BU_ALLOC(arb, struct rt_arb_internal);
175  VMOVE(arb->pt[0], rpp_min);
176  VSET(arb->pt[1], rpp_min[X], rpp_min[Y], rpp_max[Z]);
177  VSET(arb->pt[2], rpp_min[X], rpp_max[Y], rpp_max[Z]);
178  VSET(arb->pt[3], rpp_min[X], rpp_max[Y], rpp_min[Z]);
179  VSET(arb->pt[4], rpp_max[X], rpp_min[Y], rpp_min[Z]);
180  VSET(arb->pt[5], rpp_max[X], rpp_min[Y], rpp_max[Z]);
181  VMOVE(arb->pt[6], rpp_max);
182  VSET(arb->pt[7], rpp_max[X], rpp_max[Y], rpp_min[Z]);
183  arb->magic = RT_ARB_INTERNAL_MAGIC;
184 
185  /* set up internal structure */
186  RT_DB_INTERNAL_INIT(&new_intern);
187  new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
188  new_intern.idb_type = ID_ARB8;
189  new_intern.idb_meth = &OBJ[ID_ARB8];
190  new_intern.idb_ptr = (void *)arb;
191 
192  if ((dp=db_diradd(gedp->ged_wdbp->dbip, bbname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&new_intern.idb_type)) == RT_DIR_NULL) {
193  bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", bbname);
194  return GED_ERROR;
195  }
196 
197  if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &new_intern, gedp->ged_wdbp->wdb_resp) < 0) {
198  rt_db_free_internal(&new_intern);
199  bu_vls_printf(gedp->ged_result_str, "Database write error, aborting.\n");
200  }
201  }
202  } else {
203  /* basic test - BoT only at the moment */
204  struct directory *dp;
205  struct db_full_path path;
206  struct directory *obj_dp;
207  struct rt_db_internal intern;
208  struct rt_arb_internal *arb;
209  struct rt_db_internal new_intern;
210 
211  db_full_path_init(&path);
212  if (db_string_to_path(&path, gedp->ged_wdbp->dbip, argv[0])) {
213  bu_vls_printf(gedp->ged_result_str, "db_string_to_path failed for %s\n", argv[0]);
214  db_free_full_path(&path);
215  return GED_ERROR;
216  }
217  if ((obj_dp=db_lookup(gedp->ged_wdbp->dbip, DB_FULL_PATH_CUR_DIR(&path)->d_namep, LOOKUP_QUIET)) == RT_DIR_NULL) {
218  bu_vls_printf(gedp->ged_result_str, "db_lookup failed for %s\n", DB_FULL_PATH_CUR_DIR(&path)->d_namep);
219  db_free_full_path(&path);
220  return GED_ERROR;
221  }
222  if (rt_db_get_internal(&intern, obj_dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
223  bu_vls_printf(gedp->ged_result_str, "get_internal failed for %s\n", DB_FULL_PATH_CUR_DIR(&path)->d_namep);
224  db_free_full_path(&path);
225  return GED_ERROR;
226  }
227  if (intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
228  bu_vls_printf(gedp->ged_result_str, "Error: Oriented bounding box calculation is currently supported only for BoT objects\n");
229  rt_db_free_internal(&intern);
230  db_free_full_path(&path);
231  return GED_ERROR;
232  }
233 
234  BU_ALLOC(arb, struct rt_arb_internal);
235  arb->magic = RT_ARB_INTERNAL_MAGIC;
236 
237  /* set up internal structure */
238  RT_DB_INTERNAL_INIT(&new_intern);
239  new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
240  new_intern.idb_type = ID_ARB8;
241  new_intern.idb_meth = &OBJ[ID_ARB8];
242  new_intern.idb_ptr = (void *)arb;
243 
244  if (intern.idb_meth->ft_oriented_bbox) {
245  if (intern.idb_meth->ft_oriented_bbox(arb, &intern, oriented_bbox_tol) < 0) {
246  bu_vls_printf(gedp->ged_result_str, "Error: Oriented bounding box calculation failed.\n");
247  rt_db_free_internal(&intern);
248  db_free_full_path(&path);
249  return GED_ERROR;
250  }
251  }
252 
253 
254  /* Report Bounding Box Information */
256  if (!str) str = "Unknown_unit";
257 
258  /* Print Header */
259  if (print_header == 1) {
260  bu_vls_printf(gedp->ged_result_str, "Bounding Box Dimensions, Object(s)");
261  for (i = 0; i < argc - 1 ; i++) {
262  bu_vls_printf(gedp->ged_result_str, " %s, ", argv[i]);
263  }
264  bu_vls_printf(gedp->ged_result_str, " %s:\n", argv[argc-1]);
265  }
266 
267  /* Print rpp */
268  if (print_rpp == 1) {
269  bu_vls_printf(gedp->ged_result_str, "Point 1: %f, %f, %f\n", arb->pt[0][0], arb->pt[0][1], arb->pt[0][2]);
270  }
271 
272  /* Print dim info */
273  if (print_dim == 1) {
274  xlen = DIST_PT_PT(arb->pt[0], arb->pt[4])*gedp->ged_wdbp->dbip->dbi_base2local;
275  ylen = DIST_PT_PT(arb->pt[0], arb->pt[1])*gedp->ged_wdbp->dbip->dbi_base2local;
276  zlen = DIST_PT_PT(arb->pt[0], arb->pt[3])*gedp->ged_wdbp->dbip->dbi_base2local;
277  bu_vls_printf(gedp->ged_result_str, "Length: %g %s\nWidth: %g %s\nHeight: %g %s\n", xlen, str, ylen, str, zlen, str);
278  }
279 
280  if (print_vol == 1) {
281  new_intern.idb_meth->ft_volume(&vol, &new_intern);
282  /* convert to local units */
283  vol *= pow(gedp->ged_wdbp->dbip->dbi_base2local,3.0);
284  bu_vls_printf(gedp->ged_result_str, "Bounding Box Volume: %g %s^3\n", vol, str);
285  }
286 
287  if (!make_bb) {
288  /* free arb - don't need it for actual geometry */
289  rt_db_free_internal(&new_intern);
290  } else {
291 
292  if ((dp=db_diradd(gedp->ged_wdbp->dbip, bbname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&new_intern.idb_type)) == RT_DIR_NULL) {
293  bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", bbname);
294  return GED_ERROR;
295  }
296 
297  if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &new_intern, gedp->ged_wdbp->wdb_resp) < 0) {
298  rt_db_free_internal(&new_intern);
299  bu_vls_printf(gedp->ged_result_str, "Database write error, aborting.\n");
300  return GED_ERROR;
301  }
302  rt_db_free_internal(&new_intern);
303 
304  }
305  }
306 
307  return GED_OK;
308 }
309 
310 
311 /*
312  * Local Variables:
313  * tab-width: 8
314  * mode: C
315  * indent-tabs-mode: t
316  * c-file-style: "stroustrup"
317  * End:
318  * ex: shiftwidth=4 tabstop=8
319  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
int ged_bb(struct ged *gedp, int argc, const char *argv[])
Definition: bb.c:41
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 ID_ARB8
Generalized ARB. V + 7 vectors.
Definition: raytrace.h:462
#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
#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(* ft_volume)(fastf_t *, const struct rt_db_internal *)
Definition: raytrace.h:2202
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
#define DB_FULL_PATH_CUR_DIR(_pp)
Definition: db_fullpath.h:51
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
void db_full_path_init(struct db_full_path *pathp)
Definition: db_fullpath.c:40
#define GED_ERROR
Definition: ged.h:61
int idb_major_type
Definition: raytrace.h:192
Definition: color.c:49
void * memset(void *s, int c, size_t n)
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 BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define RT_DIR_SOLID
this name is a solid
Definition: raytrace.h:883
int db_string_to_path(struct db_full_path *pp, const struct db_i *dbip, const char *str)
Definition: db_fullpath.c:361
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
#define LOOKUP_QUIET
Definition: raytrace.h:893
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
void db_free_full_path(struct db_full_path *pp)
Definition: db_fullpath.c:473
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
#define BN_TOL_DIST
Definition: tol.h:109
int ged_get_obj_bounds(struct ged *gedp, int argc, const char *argv[], int use_air, point_t rpp_min, point_t rpp_max)
struct bu_vls * ged_result_str
Definition: ged.h:357
double dbi_base2local
unit conversion factors
Definition: raytrace.h:808
int(* ft_oriented_bbox)(struct rt_arb_internal *, struct rt_db_internal *, const fastf_t)
Definition: raytrace.h:2211
struct directory * db_diradd(struct db_i *, const char *name, off_t laddr, size_t len, int flags, void *ptr)
Definition: db_lookup.c:190
void * idb_ptr
Definition: raytrace.h:195
const char * bu_units_string(const double mm)
const struct rt_functab OBJ[]
Definition: table.c:159
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 GED_HELP
Definition: ged.h:62
int idb_minor_type
ID_xxx.
Definition: raytrace.h:193
Definition: color.c:51
struct resource * wdb_resp
Definition: raytrace.h:1270
double dbi_local2base
local2mm
Definition: raytrace.h:807
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
double fastf_t
Definition: defines.h:300
#define RT_ARB_INTERNAL_MAGIC
Definition: magic.h:82
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
Definition: color.c:50