BRL-CAD
nmg_simplify.c
Go to the documentation of this file.
1 /* N M G _ S I M P L I F Y . 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/nmg_simplify.c
21  *
22  * The nmg_simplify command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <string.h>
29 
30 #include "bu/cmd.h"
31 #include "rtgeom.h"
32 
33 #include "./ged_private.h"
34 
35 
36 int
37 ged_nmg_simplify(struct ged *gedp, int argc, const char *argv[])
38 {
39  struct directory *dp;
40  struct rt_db_internal nmg_intern;
41  struct rt_db_internal new_intern;
42  struct model *m;
43  struct nmgregion *r;
44  struct shell *s;
45  struct bu_ptbl faces;
46  struct face *fp;
47  int do_all=1;
48  int do_arb=0;
49  int do_tgc=0;
50  int do_poly=0;
51  char *new_name;
52  char *nmg_name;
53  int success = 0;
54  int shell_count=0;
55  int ret = GED_ERROR;
56  long i;
57 
58  static const char *usage = "[arb|tgc|poly] new_prim nmg_prim";
59 
62  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
63 
64  /* initialize result */
65  bu_vls_trunc(gedp->ged_result_str, 0);
66 
67  if (argc == 1) {
68  /* must be wanting help */
69  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s\n", argv[0], usage);
70  ret = GED_HELP;
71  goto out3;
72  } else if (argc == 3) {
73  /* FIXME: if you use the default but have a TGC, the cleanup
74  * for ARB breaks TGC.
75  */
76  do_arb = do_tgc = do_poly = do_all = 1; /* do all */
77  new_name = (char *)argv[1];
78  nmg_name = (char *)argv[2];
79  } else if (argc == 4) {
80  do_all = 0;
81  if (!bu_strncmp(argv[1], "arb", 3)) {
82  do_arb = 1;
83  } else if (!bu_strncmp(argv[1], "tgc", 3)) {
84  do_tgc = 1;
85  } else if (!bu_strncmp(argv[1], "poly", 4)) {
86  do_poly = 1;
87  } else {
89  "%s is unknown or simplification is not yet supported\n", argv[1]);
90  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
91  ret = GED_ERROR;
92  goto out3;
93  }
94  new_name = (char *)argv[2];
95  nmg_name = (char *)argv[3];
96  } else {
97  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
98  success = 0;
99  ret = GED_ERROR;
100  goto out3;
101  }
102 
103  if (db_lookup(gedp->ged_wdbp->dbip, new_name, LOOKUP_QUIET) != RT_DIR_NULL) {
104  bu_vls_printf(gedp->ged_result_str, "%s already exists\n", new_name);
105  ret = GED_ERROR;
106  goto out3;
107  }
108 
109  if ((dp=db_lookup(gedp->ged_wdbp->dbip, nmg_name, LOOKUP_QUIET)) == RT_DIR_NULL) {
110  bu_vls_printf(gedp->ged_result_str, "%s does not exist\n", nmg_name);
111  ret = GED_ERROR;
112  goto out3;
113  }
114 
115  if (rt_db_get_internal(&nmg_intern, dp, gedp->ged_wdbp->dbip, bn_mat_identity, &rt_uniresource) < 0) {
116  bu_vls_printf(gedp->ged_result_str, "rt_db_get_internal() error\n");
117  ret = GED_ERROR;
118  goto out3;
119  }
120 
121  if (nmg_intern.idb_type != ID_NMG) {
122  bu_vls_printf(gedp->ged_result_str, "%s is not an NMG solid\n", nmg_name);
123  ret = GED_ERROR;
124  goto out2;
125  }
126 
127  m = (struct model *)nmg_intern.idb_ptr;
128  NMG_CK_MODEL(m);
129 
130  /* check that all faces are planar */
131  nmg_face_tabulate(&faces, &m->magic);
132 
133  for (i = 0 ; i < BU_PTBL_END(&faces) ; i++) {
134  fp = (struct face *)BU_PTBL_GET(&faces, i);
135  if (fp->g.magic_p != NULL && *(fp->g.magic_p) != NMG_FACE_G_PLANE_MAGIC) {
136  bu_ptbl_free(&faces);
138  "%s cannot be applied to \"%s\" because it has non-planar faces\n", argv[0], nmg_name);
139  ret = GED_ERROR;
140  goto out2;
141  }
142  }
143  bu_ptbl_free(&faces);
144 
145  /* count shells */
146  shell_count = 0;
147  for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
148  for (BU_LIST_FOR(s, shell, &r->s_hd)) {
149  shell_count++;
150  }
151  }
152 
153  if (shell_count != 1) {
154  bu_vls_printf(gedp->ged_result_str, "shell count is not one\n");
155  ret = GED_ERROR;
156  goto out2;
157  }
158 
159  success = 0;
160 
161  /* see if we can get an arb by simplifying the nmg */
162  if (do_arb) {
163  struct rt_arb_internal *arb_int;
164 
165  RT_DB_INTERNAL_INIT(&new_intern);
166  BU_ALLOC(arb_int, struct rt_arb_internal);
167 
168  new_intern.idb_ptr = (void *)(arb_int);
169  new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
170  new_intern.idb_type = ID_ARB8;
171  new_intern.idb_meth = &OBJ[ID_ARB8];
172 
173  r = BU_LIST_FIRST(nmgregion, &m->r_hd);
174  s = BU_LIST_FIRST(shell, &r->s_hd);
177 
178  if (nmg_to_arb(m, arb_int)) {
179  success = 1;
180  ret = GED_OK;
181  goto out1;
182  } else {
183  rt_db_free_internal(&new_intern);
184  if (!do_all) {
185  ret = GED_ERROR;
186  goto out2;
187  }
188  }
189  }
190 
191  /* see if we can get a tgc by simplifying the nmg */
192  if (do_tgc) {
193  struct rt_tgc_internal *tgc_int;
194 
195  RT_DB_INTERNAL_INIT(&new_intern);
196  BU_ALLOC(tgc_int, struct rt_tgc_internal);
197 
198  new_intern.idb_ptr = (void *)(tgc_int);
199  new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
200  new_intern.idb_type = ID_TGC;
201  new_intern.idb_meth = &OBJ[ID_TGC];
202 
203  if (nmg_to_tgc(m, tgc_int, &gedp->ged_wdbp->wdb_tol)) {
204  success = 1;
205  ret = GED_OK;
206  goto out1;
207  } else {
208  rt_db_free_internal(&new_intern);
209  if (!do_all) {
210  ret = GED_ERROR;
211  goto out2;
212  }
213  }
214  }
215 
216  /* see if we can get a poly by simplifying the nmg */
217  if (do_poly) {
218  struct rt_pg_internal *poly_int;
219 
220  RT_DB_INTERNAL_INIT(&new_intern);
221  BU_ALLOC(poly_int, struct rt_pg_internal);
222 
223  new_intern.idb_ptr = (void *)(poly_int);
224  new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
225  new_intern.idb_type = ID_POLY;
226  new_intern.idb_meth = &OBJ[ID_POLY];
227 
228  if (nmg_to_poly(m, poly_int, &gedp->ged_wdbp->wdb_tol)) {
229  success = 1;
230  ret = GED_OK;
231  goto out1;
232  } else {
233  rt_db_free_internal(&new_intern);
234  if (!do_all) {
235  ret = GED_ERROR;
236  goto out2;
237  }
238  }
239  }
240 
241 out1:
242  r = BU_LIST_FIRST(nmgregion, &m->r_hd);
243  s = BU_LIST_FIRST(shell, &r->s_hd);
244 
245  if (BU_LIST_NON_EMPTY(&s->lu_hd))
247  "wire loops in %s have been ignored in conversion\n", nmg_name);
248 
249  if (BU_LIST_NON_EMPTY(&s->eu_hd))
251  "wire edges in %s have been ignored in conversion\n", nmg_name);
252 
253  if (s->vu_p)
255  "Single vertexuse in shell of %s has been ignored in conversion\n", nmg_name);
256 
257  dp = db_diradd(gedp->ged_wdbp->dbip, new_name,
258  RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&new_intern.idb_type);
259 
260  if (dp == RT_DIR_NULL) {
261  bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", new_name);
262  success = 0;
263  ret = GED_ERROR;
264  goto out2;
265  }
266 
267  if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &new_intern, &rt_uniresource) < 0) {
268  rt_db_free_internal(&new_intern);
269  bu_vls_printf(gedp->ged_result_str, "Database write error, aborting.\n");
270  success = 0;
271  ret = GED_ERROR;
272  goto out2;
273  }
274 
275  ret = GED_OK;
276 
277 out2:
278  rt_db_free_internal(&nmg_intern);
279 
280  if (!success) {
281  if (do_arb && !do_all) {
283  "Failed to construct an ARB equivalent to %s\n", nmg_name);
284  } else if (do_tgc && !do_all) {
286  "Failed to construct a TGC equivalent to %s\n", nmg_name);
287  } else if (do_poly && !do_all) {
289  "Failed to construct a POLY equivalent to %s\n", nmg_name);
290  } else {
292  "Failed to construct an ARB or TGC or POLY equivalent to %s\n", nmg_name);
293  }
294  }
295 
296 out3:
297  return ret;
298 }
299 
300 
301 /*
302  * Local Variables:
303  * tab-width: 8
304  * mode: C
305  * indent-tabs-mode: t
306  * c-file-style: "stroustrup"
307  * End:
308  * ex: shiftwidth=4 tabstop=8
309  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
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
int ged_nmg_simplify(struct ged *gedp, int argc, const char *argv[])
Definition: nmg_simplify.c:37
Definition: ged.h:338
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
struct db_i * dbip
Definition: raytrace.h:1266
#define ID_ARB8
Generalized ARB. V + 7 vectors.
Definition: raytrace.h:462
if lu s
Definition: nmg_mod.c:3860
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
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int nmg_to_poly(const struct model *m, struct rt_pg_internal *poly_int, const struct bn_tol *tol)
Definition: nmg_misc.c:9824
#define BU_LIST_NON_EMPTY(hp)
Definition: list.h:296
#define GED_ERROR
Definition: ged.h:61
Definition: ptbl.h:62
int idb_major_type
Definition: raytrace.h:192
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
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 nmg_shell_coplanar_face_merge(struct shell *s, const struct bn_tol *tol, const int simplify)
Definition: nmg_mod.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 BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#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 RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
struct bu_vls * ged_result_str
Definition: ged.h:357
int nmg_to_arb(const struct model *m, struct rt_arb_internal *arb_int)
Definition: nmg_misc.c:9282
#define NMG_FACE_G_PLANE_MAGIC
Definition: magic.h:125
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
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
int nmg_simplify_shell(struct shell *s)
Definition: nmg_mod.c:209
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
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
int nmg_to_tgc(const struct model *m, struct rt_tgc_internal *tgc_int, const struct bn_tol *tol)
Definition: nmg_misc.c:9522
#define ID_POLY
Polygonal faceted object.
Definition: raytrace.h: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 GED_HELP
Definition: ged.h:62
void nmg_face_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p)
Definition: nmg_info.c:2247
#define ID_TGC
Generalized Truncated General Cone.
Definition: raytrace.h:460
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312