BRL-CAD
facetize.c
Go to the documentation of this file.
1 /* F A C E T I Z E . 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/facetize.c
21  *
22  * The facetize command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <string.h>
29 
30 #include "bu/cmd.h"
31 #include "bu/getopt.h"
32 #include "rtgeom.h"
33 #include "raytrace.h"
34 
35 #include "./ged_private.h"
36 
37 
38 static union tree *
39 facetize_region_end(struct db_tree_state *tsp,
40  const struct db_full_path *pathp,
41  union tree *curtree,
42  void *client_data)
43 {
44  struct bu_list vhead;
45  union tree **facetize_tree;
46 
47  if (tsp) RT_CK_DBTS(tsp);
48  if (pathp) RT_CK_FULL_PATH(pathp);
49 
50  facetize_tree = (union tree **)client_data;
51  BU_LIST_INIT(&vhead);
52 
53  if (curtree->tr_op == OP_NOP) return curtree;
54 
55  if (*facetize_tree) {
56  union tree *tr;
57  BU_ALLOC(tr, union tree);
58  RT_TREE_INIT(tr);
59  tr->tr_op = OP_UNION;
61  tr->tr_b.tb_left = *facetize_tree;
62  tr->tr_b.tb_right = curtree;
63  *facetize_tree = tr;
64  } else {
65  *facetize_tree = curtree;
66  }
67 
68  /* Tree has been saved, and will be freed later */
69  return TREE_NULL;
70 }
71 
72 
73 int
74 ged_facetize(struct ged *gedp, int argc, const char *argv[])
75 {
76  int i;
77  int c;
78  char *newname;
79  struct rt_db_internal intern;
80  struct directory *dp;
81  int failed;
82  int nmg_use_tnurbs = 0;
83  struct db_tree_state init_state;
84  struct db_i *dbip;
85  union tree *facetize_tree;
86  struct model *nmg_model;
87 
88  static const char *usage = "[-n] [-t] [-T] new_obj old_obj [old_obj2 old_obj3 ...]";
89 
90  /* static due to jumping */
91  static int triangulate;
92  static int make_bot;
93  static int marching_cube;
94 
97  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
98 
99  /* initialize result */
100  bu_vls_trunc(gedp->ged_result_str, 0);
101 
102  /* must be wanting help */
103  if (argc == 1) {
104  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
105  return GED_HELP;
106  }
107 
108  if (argc < 3) {
109  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
110  return GED_ERROR;
111  }
112 
113  dbip = gedp->ged_wdbp->dbip;
114  RT_CHECK_DBI(dbip);
115 
116  db_init_db_tree_state(&init_state, dbip, gedp->ged_wdbp->wdb_resp);
117 
118  /* Establish tolerances */
119  init_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol;
120  init_state.ts_tol = &gedp->ged_wdbp->wdb_tol;
121 
122  /* Initial values for options, must be reset each time */
123  marching_cube = 0;
124  triangulate = 0;
125  make_bot = 1;
126 
127  /* Parse options. */
128  bu_optind = 1; /* re-init bu_getopt() */
129  while ((c=bu_getopt(argc, (char * const *)argv, "mntT")) != -1) {
130  switch (c) {
131  case 'm':
132  marching_cube = triangulate = 1;
133  /* no break, marching cubes assumes nmg for now */
134  case 'n':
135  make_bot = 0;
136  break;
137  case 'T':
138  triangulate = 1;
139  break;
140  case 't':
141  nmg_use_tnurbs = 1;
142  break;
143  default: {
144  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
145  return GED_ERROR;
146  }
147  }
148  }
149  argc -= bu_optind;
150  argv += bu_optind;
151  if (argc < 0) {
152  bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n");
153  return GED_ERROR;
154  }
155 
156  newname = (char *)argv[0];
157  argv++;
158  argc--;
159  if (argc < 0) {
160  bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n");
161  return GED_ERROR;
162  }
163 
164  if (db_lookup(dbip, newname, LOOKUP_QUIET) != RT_DIR_NULL) {
165  bu_vls_printf(gedp->ged_result_str, "error: solid '%s' already exists, aborting\n", newname);
166  return GED_ERROR;
167  }
168 
170  "facetize: tessellating primitives with tolerances a=%g, r=%g, n=%g\n",
171  gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm);
172 
173  facetize_tree = (union tree *)0;
174  nmg_model = nmg_mm();
175  init_state.ts_m = &nmg_model;
176 
177  i = db_walk_tree(dbip, argc, (const char **)argv,
178  1,
179  &init_state,
180  0, /* take all regions */
181  facetize_region_end,
182  nmg_use_tnurbs ?
185  (void *)&facetize_tree
186  );
187 
188 
189  if (i < 0) {
190  bu_vls_printf(gedp->ged_result_str, "facetize: error in db_walk_tree()\n");
191  /* Destroy NMG */
192  nmg_km(nmg_model);
193  return GED_ERROR;
194  }
195 
196  if (facetize_tree) {
197  /* Now, evaluate the boolean tree into ONE region */
198  bu_vls_printf(gedp->ged_result_str, "facetize: evaluating boolean expressions\n");
199 
200  if (!BU_SETJUMP) {
201  /* try */
202  failed = nmg_boolean(facetize_tree, nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource);
203  } else {
204  /* catch */
205  BU_UNSETJUMP;
206  bu_vls_printf(gedp->ged_result_str, "WARNING: facetization failed!!!\n");
207  db_free_tree(facetize_tree, &rt_uniresource);
208  facetize_tree = (union tree *)NULL;
209  nmg_km(nmg_model);
210  nmg_model = (struct model *)NULL;
211  return GED_ERROR;
212  } BU_UNSETJUMP;
213 
214  } else
215  failed = 1;
216 
217  if (failed) {
218  bu_vls_printf(gedp->ged_result_str, "facetize: no resulting region, aborting\n");
219  db_free_tree(facetize_tree, &rt_uniresource);
220  facetize_tree = (union tree *)NULL;
221  nmg_km(nmg_model);
222  nmg_model = (struct model *)NULL;
223  return GED_ERROR;
224  }
225  /* New region remains part of this nmg "model" */
226  NMG_CK_REGION(facetize_tree->tr_d.td_r);
227  bu_vls_printf(gedp->ged_result_str, "facetize: %s\n", facetize_tree->tr_d.td_name);
228 
229  /* Triangulate model, if requested */
230  if (triangulate && !make_bot) {
231  bu_vls_printf(gedp->ged_result_str, "facetize: triangulating resulting object\n");
232  if (!BU_SETJUMP) {
233  /* try */
234  if (marching_cube == 1)
235  nmg_triangulate_model_mc(nmg_model, &gedp->ged_wdbp->wdb_tol);
236  else
237  nmg_triangulate_model(nmg_model, &gedp->ged_wdbp->wdb_tol);
238  } else {
239  /* catch */
240  BU_UNSETJUMP;
241  bu_vls_printf(gedp->ged_result_str, "WARNING: triangulation failed!!!\n");
242  db_free_tree(facetize_tree, &rt_uniresource);
243  facetize_tree = (union tree *)NULL;
244  nmg_km(nmg_model);
245  nmg_model = (struct model *)NULL;
246  return GED_ERROR;
247  } BU_UNSETJUMP;
248  }
249 
250  if (make_bot) {
251  struct rt_bot_internal *bot;
252  struct nmgregion *r;
253  struct shell *s;
254 
255  bu_vls_printf(gedp->ged_result_str, "facetize: converting to BOT format\n");
256 
257  /* WTF, FIXME: this is only dumping the first shell of the first region */
258 
259  r = BU_LIST_FIRST(nmgregion, &nmg_model->r_hd);
260  if (r && BU_LIST_NEXT(nmgregion, &r->l) != (struct nmgregion *)&nmg_model->r_hd)
261  bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one region, only facetizing the first\n");
262 
263  s = BU_LIST_FIRST(shell, &r->s_hd);
264  if (s && BU_LIST_NEXT(shell, &s->l) != (struct shell *)&r->s_hd)
265  bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one shell, only facetizing the first\n");
266 
267  if (!BU_SETJUMP) {
268  /* try */
269  bot = (struct rt_bot_internal *)nmg_bot(s, &gedp->ged_wdbp->wdb_tol);
270  } else {
271  /* catch */
272  BU_UNSETJUMP;
273  bu_vls_printf(gedp->ged_result_str, "WARNING: conversion to BOT failed!\n");
274  db_free_tree(facetize_tree, &rt_uniresource);
275  facetize_tree = (union tree *)NULL;
276  nmg_km(nmg_model);
277  nmg_model = (struct model *)NULL;
278  return GED_ERROR;
279  } BU_UNSETJUMP;
280 
281  nmg_km(nmg_model);
282  nmg_model = (struct model *)NULL;
283 
284  /* Export BOT as a new solid */
285  RT_DB_INTERNAL_INIT(&intern);
286  intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
287  intern.idb_type = ID_BOT;
288  intern.idb_meth = &OBJ[ID_BOT];
289  intern.idb_ptr = (void *) bot;
290  } else {
291 
292  bu_vls_printf(gedp->ged_result_str, "facetize: converting NMG to database format\n");
293 
294  /* Export NMG as a new solid */
295  RT_DB_INTERNAL_INIT(&intern);
296  intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
297  intern.idb_type = ID_NMG;
298  intern.idb_meth = &OBJ[ID_NMG];
299  intern.idb_ptr = (void *)nmg_model;
300  nmg_model = (struct model *)NULL;
301  }
302 
303  dp=db_diradd(dbip, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type);
304  if (dp == RT_DIR_NULL) {
305  bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", newname);
306  return GED_ERROR;
307  }
308 
309  if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource) < 0) {
310  bu_vls_printf(gedp->ged_result_str, "Failed to write %s to database\n", newname);
311  rt_db_free_internal(&intern);
312  return GED_ERROR;
313  }
314 
315  facetize_tree->tr_d.td_r = (struct nmgregion *)NULL;
316 
317  /* Free boolean tree, and the regions in it */
318  db_free_tree(facetize_tree, &rt_uniresource);
319  facetize_tree = (union tree *)NULL;
320 
321  return GED_OK;
322 }
323 
324 
325 /*
326  * Local Variables:
327  * tab-width: 8
328  * mode: C
329  * indent-tabs-mode: t
330  * c-file-style: "stroustrup"
331  * End:
332  * ex: shiftwidth=4 tabstop=8
333  */
void nmg_triangulate_model_mc(struct model *m, const struct bn_tol *tol)
Definition: nmg_tri_mc.c:768
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
Definition: raytrace.h:800
struct model ** ts_m
ptr to ptr to NMG "model"
Definition: raytrace.h:1072
#define RT_CHECK_DBI(_p)
Definition: raytrace.h:828
struct rt_bot_internal * nmg_bot(struct shell *s, const struct bn_tol *tol)
Definition: nmg_misc.c:10826
Definition: list.h:118
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 nmgregion * td_r
ptr to NMG region
Definition: raytrace.h:1168
#define OP_NOP
Leaf with no effect.
Definition: raytrace.h:1132
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
if lu s
Definition: nmg_mod.c:3860
union tree * nmg_booltree_leaf_tnurb(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *client_data)
Definition: nmg_bool.c:1241
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define ID_BOT
Bag o' triangles.
Definition: raytrace.h:488
#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
struct region * tb_regionp
ptr to containing region
Definition: raytrace.h:1148
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 bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
struct rt_tess_tol wdb_ttol
Definition: raytrace.h:1268
#define GED_ERROR
Definition: ged.h:61
#define RT_TREE_INIT(_p)
Definition: raytrace.h:1189
union tree * tb_left
Definition: raytrace.h:1149
double rel
rel dist tol
Definition: raytrace.h:181
int idb_major_type
Definition: raytrace.h:192
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
void db_init_db_tree_state(struct db_tree_state *tsp, struct db_i *dbip, struct resource *resp)
Definition: db_tree.c:93
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define RT_DIR_SOLID
this name is a solid
Definition: raytrace.h:883
#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 ID_NMG
n-Manifold Geometry solid
Definition: raytrace.h:469
#define TREE_NULL
Definition: raytrace.h:1181
void nmg_km(struct model *m)
Definition: nmg_mk.c:1634
void db_free_tree(union tree *tp, struct resource *resp)
Definition: db_tree.c:1296
union tree * nmg_booltree_leaf_tess(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *client_data)
Definition: nmg_bool.c:1175
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
struct tree::tree_node tr_b
void nmg_triangulate_model(struct model *m, const struct bn_tol *tol)
Definition: nmg_tri.c:3818
struct tree::tree_nmgregion tr_d
struct bu_vls * ged_result_str
Definition: ged.h:357
#define RT_CK_FULL_PATH(_p)
Definition: db_fullpath.h:59
struct model * nmg_mm(void)
Definition: nmg_mk.c:235
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
union tree * tb_right
Definition: raytrace.h:1150
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * idb_ptr
Definition: raytrace.h:195
struct bn_tol wdb_tol
Definition: raytrace.h:1269
const struct rt_functab OBJ[]
Definition: table.c:159
const struct rt_tess_tol * ts_ttol
Tessellation tolerance.
Definition: raytrace.h:1070
#define RT_CK_DBTS(_p)
Definition: raytrace.h:1084
double abs
absolute dist tol
Definition: raytrace.h:180
#define BU_UNSETJUMP
Definition: parallel.h:193
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 REGION_NULL
Definition: raytrace.h:558
#define GED_HELP
Definition: ged.h:62
const char * td_name
If non-null, dynamic string describing heritage of this region.
Definition: raytrace.h:1167
double norm
normal tol
Definition: raytrace.h:182
struct resource * wdb_resp
Definition: raytrace.h:1270
#define BU_SETJUMP
Definition: parallel.h:192
int ged_facetize(struct ged *gedp, int argc, const char *argv[])
Definition: facetize.c:74
int db_walk_tree(struct db_i *dbip, int argc, const char **argv, int ncpu, const struct db_tree_state *init_state, int(*reg_start_func)(struct db_tree_state *, const struct db_full_path *, const struct rt_comb_internal *, void *client_data), union tree *(*reg_end_func)(struct db_tree_state *, const struct db_full_path *, union tree *, void *client_data), union tree *(*leaf_func)(struct db_tree_state *, const struct db_full_path *, struct rt_db_internal *, void *client_data), void *client_data)
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int nmg_boolean(union tree *tp, struct model *m, const struct bn_tol *tol, struct resource *resp)
Definition: nmg_bool.c:1523
const struct bn_tol * ts_tol
Math tolerance.
Definition: raytrace.h:1071
#define OP_UNION
Binary: L union R.
Definition: raytrace.h:1127
#define BU_LIST_NEXT(structure, hp)
Definition: list.h:316
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312