BRL-CAD
bot_fuse.c
Go to the documentation of this file.
1 /* B O T _ F U S 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/bot_fuse.c
21  *
22  * The bot_fuse 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 "bu/parallel.h"
34 #include "rtgeom.h"
35 #include "plot3.h"
36 
37 #include "./ged_private.h"
38 
39 
40 static size_t
41 show_dangling_edges(struct ged *gedp, const uint32_t *magic_p, const char *name, int out_type)
42 {
43  FILE *plotfp = NULL;
44  const char *manifolds = NULL;
45  const struct edgeuse *eur;
46  int done;
47  point_t pt1, pt2;
48  size_t i, cnt;
49  struct bn_vlblock *vbp = NULL;
50  struct bu_list *vhead = NULL;
51  struct bu_ptbl faces;
52  struct bu_vls plot_file_name = BU_VLS_INIT_ZERO;
53  struct edgeuse *eu = NULL;
54  struct face *fp = NULL;
55  struct faceuse *fu, *fu1, *fu2;
56  struct faceuse *newfu = NULL;
57  struct loopuse *lu = NULL;
58 
59  /* out_type: 0 = none, 1 = show, 2 = plot */
60  if (out_type < 0 || out_type > 2) {
61  bu_log("Internal error, open edge test failed.\n");
62  return 0;
63  }
64 
65  if (out_type == 1) {
66  vbp = rt_vlblock_init();
67  vhead = rt_vlblock_find(vbp, 0xFF, 0xFF, 0x00);
68  }
69 
70  bu_ptbl_init(&faces, 64, "faces buffer");
71  nmg_face_tabulate(&faces, magic_p);
72 
73  cnt = 0;
74  for (i = 0; i < (size_t)BU_PTBL_END(&faces) ; i++) {
75  fp = (struct face *)BU_PTBL_GET(&faces, i);
76  NMG_CK_FACE(fp);
77  fu = fu1 = fp->fu_p;
78  NMG_CK_FACEUSE(fu1);
79  fu2 = fp->fu_p->fumate_p;
80  NMG_CK_FACEUSE(fu2);
81  done = 0;
82  while (!done) {
83  NMG_CK_FACEUSE(fu);
84  for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
85  NMG_CK_LOOPUSE(lu);
86  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
87  for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
88  NMG_CK_EDGEUSE(eu);
90  newfu = eur->up.lu_p->up.fu_p;
91  while (manifolds &&
92  NMG_MANIFOLDS(manifolds, newfu) &
93  NMG_2MANIFOLD &&
94  eur != eu->eumate_p) {
95  eur = nmg_radial_face_edge_in_shell(eur->eumate_p);
96  newfu = eur->up.lu_p->up.fu_p;
97  }
98  if (eur == eu->eumate_p) {
99  VMOVE(pt1, eu->vu_p->v_p->vg_p->coord);
100  VMOVE(pt2, eu->eumate_p->vu_p->v_p->vg_p->coord);
101  if (out_type == 1) {
102  BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt1, BN_VLIST_LINE_MOVE);
103  BN_ADD_VLIST(vbp->free_vlist_hd, vhead, pt2, BN_VLIST_LINE_DRAW);
104  } else if (out_type == 2) {
105  if (!plotfp) {
106  bu_vls_sprintf(&plot_file_name, "%s.%p.pl", name, (void *)magic_p);
107  if ((plotfp = fopen(bu_vls_addr(&plot_file_name), "wb")) == (FILE *)NULL) {
108  bu_vls_free(&plot_file_name);
109  bu_log("Error, unable to create plot file (%s), open edge test failed.\n",
110  bu_vls_addr(&plot_file_name));
111  return 0;
112  }
113  }
114  pdv_3line(plotfp, pt1, pt2);
115  }
116  cnt++;
117  }
118  }
119  }
120  }
121  if (fu == fu1) fu = fu2;
122  if (fu == fu2) done = 1;
123  };
124 
125  }
126 
127  if (out_type == 1) {
128  /* Add overlay */
129  _ged_cvt_vlblock_to_solids(gedp, vbp, name, 0);
130  rt_vlblock_free(vbp);
131  bu_log("Showing open edges...\n");
132  } else if (out_type == 2) {
133  if (plotfp) {
134  (void)fclose(plotfp);
135  bu_log("Wrote plot file (%s)\n", bu_vls_addr(&plot_file_name));
136  bu_vls_free(&plot_file_name);
137  }
138  }
139  bu_ptbl_free(&faces);
140 
141  return cnt;
142 }
143 
144 
145 int
146 ged_bot_fuse(struct ged *gedp, int argc, const char **argv)
147 {
148  struct directory *old_dp, *new_dp;
149  struct rt_db_internal intern, intern2;
150  struct rt_bot_internal *bot;
151  int count=0;
152  static const char *usage = "new_bot old_bot";
153 
154  struct model *m;
155  struct nmgregion *r;
156  int ret, c, i;
157  struct bn_tol *tol = &gedp->ged_wdbp->wdb_tol;
158  int total = 0;
159  volatile int out_type = 0; /* open edge output type: 0 = none, 1 = show, 2 = plot */
160  size_t open_cnt;
161  struct bu_vls name_prefix = BU_VLS_INIT_ZERO;
162 
163  /* bu_getopt() options */
164  static const char *bot_fuse_options = "sp";
165  static const char *bot_fuse_options_str = "[-s|-p]";
166 
169  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
170 
171  /* initialize result */
172  bu_vls_trunc(gedp->ged_result_str, 0);
173 
174  /* must be wanting help */
175  if (argc != 3 && argc != 4) {
176  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s %s", argv[0], bot_fuse_options_str, usage);
177  return GED_HELP;
178  }
179 
180  /* Turn off getopt's error messages */
181  bu_opterr = 0;
182  bu_optind = 1;
183 
184  /* get all the option flags from the command line */
185  while ((c=bu_getopt(argc, (char **)argv, bot_fuse_options)) != -1) {
186  switch (c) {
187  case 's':
188  {
189  out_type = 1; /* show open edges */
190  break;
191  }
192  case 'p':
193  {
194  out_type = 2; /* plot open edges */
195  break;
196  }
197  default :
198  {
199  bu_vls_printf(gedp->ged_result_str, "Unknown option: '%c'", c);
200  return GED_HELP;
201  }
202  }
203  }
204 
205  i = argc - 2;
206 
207  bu_log("%s: start\n", argv[0]);
208 
209  GED_DB_LOOKUP(gedp, old_dp, argv[i+1], LOOKUP_NOISY, GED_ERROR & GED_QUIET);
210  GED_DB_GET_INTERNAL(gedp, &intern, old_dp, bn_mat_identity, &rt_uniresource, GED_ERROR);
211 
212  if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
213  bu_vls_printf(gedp->ged_result_str, "%s: %s is not a BOT solid!\n", argv[0], argv[i+1]);
214  return GED_ERROR;
215  }
216 
217  /* create nmg model structure */
218  m = nmg_mm();
219 
220  /* place bot in nmg structure */
221  bu_log("%s: running rt_bot_tess\n", argv[0]);
222  ret = rt_bot_tess(&r, m, &intern, &gedp->ged_wdbp->wdb_ttol, tol);
223 
224  /* free internal representation of original bot */
225  rt_db_free_internal(&intern);
226 
227  if (ret != 0) {
228  bu_vls_printf(gedp->ged_result_str, "%s: %s fuse failed (1).\n", argv[0], argv[i+1]);
229  nmg_km(m);
230  return GED_ERROR;
231  }
232 
233  total = 0;
234 
235  /* Step 1 -- the vertices. */
236  bu_log("%s: running nmg_vertex_fuse\n", argv[0]);
237  count = nmg_vertex_fuse(&m->magic, tol);
238  total += count;
239  bu_log("%s: %s, %d vertex fused\n", argv[0], argv[i+1], count);
240 
241  /* Step 1.5 -- break edges on vertices, before fusing edges */
242  bu_log("%s: running nmg_break_e_on_v\n", argv[0]);
243  count = nmg_break_e_on_v(&m->magic, tol);
244  total += count;
245  bu_log("%s: %s, %d broke 'e' on 'v'\n", argv[0], argv[i+1], count);
246 
247  if (total) {
248  struct nmgregion *r2;
249  struct shell *s;
250 
251  bu_log("%s: running nmg_make_faces_within_tol\n", argv[0]);
252 
253  /* vertices and/or edges have been moved,
254  * may have created out-of-tolerance faces
255  */
256 
257  for (BU_LIST_FOR(r2, nmgregion, &m->r_hd)) {
258  for (BU_LIST_FOR(s, shell, &r2->s_hd))
260  }
261  }
262 
263  /* Step 2 -- the face geometry */
264  bu_log("%s: running nmg_model_face_fuse\n", argv[0]);
265  count = nmg_model_face_fuse(m, tol);
266  total += count;
267  bu_log("%s: %s, %d faces fused\n", argv[0], argv[i+1], count);
268 
269  /* Step 3 -- edges */
270  bu_log("%s: running nmg_edge_fuse\n", argv[0]);
271  count = nmg_edge_fuse(&m->magic, tol);
272  total += count;
273 
274  bu_log("%s: %s, %d edges fused\n", argv[0], argv[i+1], count);
275 
276  bu_log("%s: %s, %d total fused\n", argv[0], argv[i+1], total);
277 
278  if (!BU_SETJUMP) {
279  /* try */
280 
281  /* convert the nmg model back into a bot */
282  bot = nmg_bot(BU_LIST_FIRST(shell, &r->s_hd), tol);
283 
284  bu_vls_sprintf(&name_prefix, "open_edges.%s", argv[i]);
285  bu_log("%s: running show_dangling_edges\n", argv[0]);
286  open_cnt = show_dangling_edges(gedp, &m->magic, bu_vls_addr(&name_prefix), out_type);
287  bu_log("%s: WARNING %ld open edges, new BOT may be invalid!!!\n", argv[0], open_cnt);
288  bu_vls_free(&name_prefix);
289 
290  /* free the nmg model structure */
291  nmg_km(m);
292  } else {
293  /* catch */
294  BU_UNSETJUMP;
295  bu_vls_printf(gedp->ged_result_str, "%s: %s fuse failed (2).\n", argv[0], argv[i+1]);
296  return GED_ERROR;
297  } BU_UNSETJUMP;
298 
299  RT_DB_INTERNAL_INIT(&intern2);
300  intern2.idb_major_type = DB5_MAJORTYPE_BRLCAD;
301  intern2.idb_type = ID_BOT;
302  intern2.idb_meth = &OBJ[ID_BOT];
303  intern2.idb_ptr = (void *)bot;
304 
305  GED_DB_DIRADD(gedp, new_dp, argv[i], RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern2.idb_type, GED_ERROR);
306  GED_DB_PUT_INTERNAL(gedp, new_dp, &intern2, &rt_uniresource, GED_ERROR);
307 
308  bu_log("%s: Created new BOT (%s)\n", argv[0], argv[i]);
309  bu_log("%s: Done.\n", argv[0]);
310 
311  return GED_OK;
312 }
313 
314 
315 /*
316  * Local Variables:
317  * tab-width: 8
318  * mode: C
319  * indent-tabs-mode: t
320  * c-file-style: "stroustrup"
321  * End:
322  * ex: shiftwidth=4 tabstop=8
323  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_DB_DIRADD(_gedp, _dp, _name, _laddr, _len, _dirflags, _ptr, _flags)
Definition: ged.h:213
#define GED_OK
Definition: ged.h:55
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
#define NMG_EDGEUSE_MAGIC
Definition: magic.h:120
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
int nmg_edge_fuse(const uint32_t *magic_p, const struct bn_tol *tol)
Definition: nmg_fuse.c:1062
void rt_vlblock_free(struct bn_vlblock *vbp)
Definition: vlist.c:78
int nmg_model_face_fuse(struct model *m, const struct bn_tol *tol)
Definition: nmg_fuse.c:1677
struct rt_bot_internal * nmg_bot(struct shell *s, const struct bn_tol *tol)
Definition: nmg_misc.c:10826
Definition: list.h:118
void nmg_make_faces_within_tol(struct shell *s, const struct bn_tol *tol)
Definition: nmg_misc.c:8463
Definition: ged.h:338
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
if lu s
Definition: nmg_mod.c:3860
Definition: clone.c:90
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
#define GED_DB_LOOKUP(_gedp, _dp, _name, _noisy, _flags)
Definition: ged.h:223
lu
Definition: nmg_mod.c:3855
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 rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
struct bn_vlblock * rt_vlblock_init(void)
Definition: vlist.c:71
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
NMG_CK_LOOPUSE(lu)
Definition: ptbl.h:62
#define GED_DB_PUT_INTERNAL(_gedp, _dp, _intern, _resource, _flags)
Definition: ged.h:243
struct bu_list * rt_vlblock_find(struct bn_vlblock *vbp, int r, int g, int b)
Definition: vlist.c:98
int idb_major_type
Definition: raytrace.h:192
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
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
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
void bu_vls_sprintf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:707
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
int nmg_vertex_fuse(const uint32_t *magic_p, const struct bn_tol *tol)
Definition: nmg_fuse.c:306
void nmg_km(struct model *m)
Definition: nmg_mk.c:1634
#define GED_QUIET
Definition: ged.h:64
int rt_bot_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: bot.c:761
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
#define BN_ADD_VLIST(_free_hd, _dest_hd, pnt, draw)
Definition: vlist.h:123
Support for uniform tolerances.
Definition: tol.h:71
#define BU_LIST_FIRST_MAGIC(hp)
Definition: list.h:416
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
void pdv_3line(register FILE *plotfp, const fastf_t *a, const fastf_t *b)
Definition: plot3.c:642
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
void _ged_cvt_vlblock_to_solids(struct ged *gedp, struct bn_vlblock *vbp, const char *name, int copy)
Definition: draw.c:554
struct model * nmg_mm(void)
Definition: nmg_mk.c:235
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 bu_opterr
Definition: globals.c:88
#define BU_UNSETJUMP
Definition: parallel.h:193
eu1 up magic_p
Definition: nmg_mod.c:3915
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define LOOKUP_NOISY
Definition: raytrace.h:892
#define GED_HELP
Definition: ged.h:62
int idb_minor_type
ID_xxx.
Definition: raytrace.h:193
#define GED_DB_GET_INTERNAL(_gedp, _intern, _dp, _mat, _resource, _flags)
Definition: ged.h:233
#define BU_SETJUMP
Definition: parallel.h:192
void nmg_face_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p)
Definition: nmg_info.c:2247
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
const struct edgeuse * nmg_radial_face_edge_in_shell(const struct edgeuse *eu)
Definition: nmg_info.c:1021
struct bu_list * free_vlist_hd
where to get/put free vlists
Definition: vlist.h:175
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
Definition: vls.h:56
int nmg_break_e_on_v(const uint32_t *magic_p, const struct bn_tol *tol)
Definition: nmg_fuse.c:1802
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
int ged_bot_fuse(struct ged *gedp, int argc, const char **argv)
Definition: bot_fuse.c:146