BRL-CAD
test_shape_recognition.cpp
Go to the documentation of this file.
1 #include "common.h"
2 
3 #include <map>
4 #include <set>
5 #include <queue>
6 #include <list>
7 #include <vector>
8 #include <iostream>
9 #include <fstream>
10 #include <algorithm>
11 
12 #include "vmath.h"
13 #include "raytrace.h"
14 #include "wdb.h"
15 #include "plot3.h"
16 #include "opennurbs.h"
17 #include "brep.h"
18 #include "../libbrep/shape_recognition.h"
19 
20 
21 struct model *
23 {
24  struct bu_vls prim_name = BU_VLS_INIT_ZERO;
25  bu_vls_sprintf(&prim_name, "nmg_%s", bu_vls_addr(data->key));
26  std::set<int> b_verts;
27  std::vector<int> b_verts_array;
28  std::map<int, int> b_verts_to_verts;
29  struct model *m = nmg_mm();
30  struct nmgregion *r = nmg_mrsv(m);
31  struct shell *s = BU_LIST_FIRST(shell, &(r)->s_hd);
32  struct faceuse **fu; /* array of faceuses */
33  struct vertex **verts; /* Array of pointers to vertex structs */
34  struct vertex ***loop_verts; /* Array of pointers to vertex structs to pass to nmg_cmface */
35 
36  struct bn_tol nmg_tol = {BN_TOL_MAGIC, BN_TOL_DIST, BN_TOL_DIST * BN_TOL_DIST, 1e-6, 1.0 - 1e-6 };
37 
38  int point_cnt = 0;
39  int face_cnt = 0;
40  int max_edge_cnt = 0;
41 
42  // One loop to a face, and the object data has the set of loops that make
43  // up this object.
44  for (int s_it = 0; s_it < data->loops_cnt; s_it++) {
45  ON_BrepLoop *b_loop = &(data->brep->m_L[data->loops[s_it]]);
46  ON_BrepFace *b_face = b_loop->Face();
47  face_cnt++;
48  if (b_loop->m_ti.Count() > max_edge_cnt) max_edge_cnt = b_loop->m_ti.Count();
49  for (int ti = 0; ti < b_loop->m_ti.Count(); ti++) {
50  ON_BrepTrim& trim = b_face->Brep()->m_T[b_loop->m_ti[ti]];
51  ON_BrepEdge& edge = b_face->Brep()->m_E[trim.m_ei];
52  if (b_verts.find(edge.Vertex(0)->m_vertex_index) == b_verts.end()) {
53  b_verts.insert(edge.Vertex(0)->m_vertex_index);
54  b_verts_array.push_back(edge.Vertex(0)->m_vertex_index);
55  b_verts_to_verts[edge.Vertex(0)->m_vertex_index] = b_verts_array.size()-1;
56  }
57  if (b_verts.find(edge.Vertex(1)->m_vertex_index) == b_verts.end()) {
58  b_verts.insert(edge.Vertex(1)->m_vertex_index);
59  b_verts_array.push_back(edge.Vertex(1)->m_vertex_index);
60  b_verts_to_verts[edge.Vertex(1)->m_vertex_index] = b_verts_array.size()-1;
61  }
62  }
63  }
64 
65  point_cnt = b_verts.size();
66 
67  verts = (struct vertex **)bu_calloc(point_cnt, sizeof(struct vertex *), "brep_to_nmg: verts");
68  loop_verts = (struct vertex ***) bu_calloc(max_edge_cnt, sizeof(struct vertex **), "brep_to_nmg: loop_verts");
69  fu = (struct faceuse **) bu_calloc(face_cnt, sizeof(struct faceuse *), "brep_to_nmg: fu");
70 
71  // Make the faces
72  int face_count = 0;
73  for (int s_it = 0; s_it < data->loops_cnt; s_it++) {
74  int loop_length = 0;
75  ON_BrepLoop *b_loop = &(data->brep->m_L[data->loops[s_it]]);
76  ON_BrepFace *b_face = b_loop->Face();
77  for (int ti = 0; ti < b_loop->m_ti.Count(); ti++) {
78  ON_BrepTrim& trim = b_face->Brep()->m_T[b_loop->m_ti[ti]];
79  ON_BrepEdge& edge = b_face->Brep()->m_E[trim.m_ei];
80  if (trim.m_bRev3d) {
81  loop_verts[loop_length] = &(verts[b_verts_to_verts[edge.Vertex(0)->m_vertex_index]]);
82  } else {
83  loop_verts[loop_length] = &(verts[b_verts_to_verts[edge.Vertex(1)->m_vertex_index]]);
84  }
85  loop_length++;
86  }
87  fu[face_count] = nmg_cmface(s, loop_verts, loop_length);
88  face_count++;
89  }
90 
91  for (int p = 0; p < point_cnt; p++) {
92  ON_3dPoint pt = data->brep->m_V[b_verts_array[p]].Point();
93  point_t nmg_pt;
94  nmg_pt[0] = pt.x;
95  nmg_pt[1] = pt.y;
96  nmg_pt[2] = pt.z;
97  nmg_vertex_gv(verts[p], pt);
98  }
99 
100  for (int f = 0; f < face_cnt; f++) {
101  nmg_fu_planeeqn(fu[f], &nmg_tol);
102  }
103 
104  nmg_fix_normals(s, &nmg_tol);
105  (void)nmg_mark_edges_real(&s->l.magic);
106  /* Compute "geometry" for region and shell */
107  nmg_region_a(r, &nmg_tol);
108 
109  /* Create the nmg primitive */
110  mk_nmg(wdbp, bu_vls_addr(&prim_name), m);
111 
112  bu_vls_free(&prim_name);
113 
114  return m;
115 }
116 
117 
118 int
120 {
121  if (data->type == PLANAR_VOLUME) {
122  // BRL-CAD's arbn primitive does not support concave shapes, and we want to use
123  // simpler primitives than the generic nmg if the opportunity arises. A heuristic
124  // along the following lines may help:
125  //
126  // Step 1. Check the number of vertices. If the number is small enough that the
127  // volume might conceivably be expressed by an arb4-arb8, try that first.
128  //
129  // Step 2. If the arb4-arb8 test fails, do the convex hull and see if all points
130  // are used by the hull. If so, the shape is convex and may be expressed
131  // as an arbn.
132  //
133  // Step 3. If the arbn test fails, construct sets of contiguous concave faces using
134  // the set of edges with one or more vertices not in the convex hull. If
135  // those shapes are all convex, construct an arbn tree (or use simpler arb
136  // shapes if the subtractions may be so expressed).
137  //
138  // Step 4. If the subtraction volumes in Step 3 are still not convex, cut our losses
139  // and proceed to the nmg primitive. It may conceivably be worth some
140  // additional searches to spot convex subsets of shapes that can be more
141  // simply represented, but that is not particularly simple to do well
142  // and should wait until it is clear we would get a benefit from it. Look
143  // at the arbn tessellation routine for a guide on how to set up the
144  // nmg - that's the most general of the arb* primitives and should be
145  // relatively close to what is needed here.
146  (void)brep_to_nmg(data, wdbp);
147  return 1;
148  } else {
149  return 0;
150  }
151 }
152 
153 int
155 {
156  if (data->type == CYLINDER) {
157  struct bu_vls prim_name = BU_VLS_INIT_ZERO;
158  bu_vls_sprintf(&prim_name, "rcc_%s", bu_vls_addr(data->key));
159 
160  mk_rcc(wdbp, bu_vls_addr(&prim_name), data->params->origin, data->params->hv, data->params->radius);
161  bu_vls_free(&prim_name);
162  return 1;
163  }
164  return 0;
165 }
166 
167 int
169 {
170  if (data->type == CONE) {
171  struct bu_vls prim_name = BU_VLS_INIT_ZERO;
172  bu_vls_sprintf(&prim_name, "trc_%s", bu_vls_addr(data->key));
173 
174  mk_cone(wdbp, bu_vls_addr(&prim_name), data->params->origin, data->params->hv, data->params->height, data->params->radius, data->params->r2);
175  bu_vls_free(&prim_name);
176  return 1;
177  }
178  return 0;
179 }
180 
181 
182 int
184 {
185  struct bu_vls brep_name = BU_VLS_INIT_ZERO;
186  bu_vls_sprintf(&brep_name, "brep_%s", bu_vls_addr(data->key));
187  switch (data->type) {
188  case COMB:
189  bu_log("TODO - make comb here\n");
190  return 0;
191  break;
192  case PLANAR_VOLUME:
193  bu_vls_free(&brep_name);
194  return subbrep_to_csg_planar(data, wdbp);
195  break;
196  case CYLINDER:
197  bu_vls_free(&brep_name);
198  return subbrep_to_csg_cylinder(data, wdbp);
199  break;
200  case CONE:
201  bu_vls_free(&brep_name);
202  return subbrep_to_csg_conic(data, wdbp);
203  return 0;
204  break;
205  case SPHERE:
206  bu_vls_free(&brep_name);
207  return 0;
208  break;
209  case ELLIPSOID:
210  bu_vls_free(&brep_name);
211  return 0;
212  break;
213  case TORUS:
214  bu_vls_free(&brep_name);
215  return 0;
216  break;
217  default:
218  if (data->local_brep) {
219  mk_brep(wdbp, bu_vls_addr(&brep_name), data->local_brep);
220  } else {
221  bu_log("Warning - mk_brep called but data->local_brep is empty\n");
222  }
223  bu_vls_free(&brep_name);
224 
225  return 0; /* BREP */
226  break;
227  }
228 
229  /* Shouldn't get here */
230  return 0;
231 }
232 
233 int
234 main(int argc, char *argv[])
235 {
236  struct db_i *dbip;
237  struct rt_wdb *wdbp;
238  struct directory *dp;
239  struct rt_db_internal intern;
240  struct rt_brep_internal *brep_ip = NULL;
241 
242  if (argc != 3) {
243  bu_exit(1, "Usage: %s file.g object", argv[0]);
244  }
245 
246  dbip = db_open(argv[1], DB_OPEN_READWRITE);
247  if (dbip == DBI_NULL) {
248  bu_exit(1, "ERROR: Unable to read from %s\n", argv[1]);
249  }
250 
251  wdbp = wdb_dbopen(dbip, RT_WDB_TYPE_DB_DISK);
252 
253  if (db_dirbuild(dbip) < 0)
254  bu_exit(1, "ERROR: Unable to read from %s\n", argv[1]);
255 
256  dp = db_lookup(dbip, argv[2], LOOKUP_QUIET);
257  if (dp == RT_DIR_NULL) {
258  bu_exit(1, "ERROR: Unable to look up object %s\n", argv[2]);
259  }
260 
261  RT_DB_INTERNAL_INIT(&intern)
262 
263  if (rt_db_get_internal(&intern, dp, dbip, NULL, &rt_uniresource) < 0) {
264  bu_exit(1, "ERROR: Unable to get internal representation of %s\n", argv[2]);
265  }
266 
267  if (intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BREP) {
268  bu_exit(1, "ERROR: object %s does not appear to be of type BRep\n", argv[2]);
269  } else {
270  brep_ip = (struct rt_brep_internal *)intern.idb_ptr;
271  }
272  RT_BREP_CK_MAGIC(brep_ip);
273 
274  ON_Brep *brep = brep_ip->brep;
275 
276  struct bu_ptbl *subbreps = find_subbreps(brep);
277  for (unsigned int i = 0; i < BU_PTBL_LEN(subbreps); i++){
278  struct subbrep_object_data *obj = (struct subbrep_object_data *)BU_PTBL_GET(subbreps, i);
279  //print_subbrep_object(obj, "");
280  if (obj->type == BREP) {
281  int ret = subbrep_split(obj);
282  if (!ret) {
283  (void)make_shape(obj, wdbp);
284  } else {
285  // first, make the comb
286  (void)make_shape(obj, wdbp);
287  // next, add its children
288  for (unsigned int j = 0; j < BU_PTBL_LEN(obj->children); j++){
289  struct subbrep_object_data *cobj = (struct subbrep_object_data *)BU_PTBL_GET(obj->children, j);
290  // print_subbrep_object(cobj, " ");
291  if (cobj->type == CYLINDER) (void)make_shape(cobj, wdbp);
292  if (cobj->type == CONE) (void)make_shape(cobj, wdbp);
293  //subbrep_csg_assemble(cobj);
294  }
295  }
296  } else {
297  (void)make_shape(obj, wdbp);
298  }
299  subbrep_object_free(obj);
300  BU_PUT(obj, struct subbrep_object_data);
301  }
302  bu_ptbl_free(subbreps);
303  BU_PUT(subbreps, struct bu_ptbl);
304 
305  db_close(dbip);
306 
307  return 0;
308 }
309 
310 // Local Variables:
311 // tab-width: 8
312 // mode: C++
313 // c-basic-offset: 4
314 // indent-tabs-mode: t
315 // c-file-style: "stroustrup"
316 // End:
317 // ex: shiftwidth=4 tabstop=8
void nmg_fix_normals(struct shell *s_orig, const struct bn_tol *tol)
Definition: nmg_misc.c:3505
Definition: raytrace.h:800
int mk_rcc(struct rt_wdb *fp, const char *name, const point_t base, const vect_t height, fastf_t radius)
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 nmg_fu_planeeqn(struct faceuse *fu, const struct bn_tol *tol)
Definition: nmg_mod.c:1311
if lu s
Definition: nmg_mod.c:3860
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
void nmg_vertex_gv(struct vertex *v, const fastf_t *pt)
Definition: nmg_mk.c:1668
#define BN_TOL_MAGIC
Definition: magic.h:74
struct bu_ptbl * find_subbreps(ON_Brep *brep)
Header file for the BRL-CAD common definitions.
int subbrep_to_csg_conic(struct subbrep_object_data *data, struct rt_wdb *wdbp)
int mk_cone(struct rt_wdb *fp, const char *name, const point_t base, const vect_t dirv, fastf_t height, fastf_t rad1, fastf_t rad2)
int subbrep_to_csg_planar(struct subbrep_object_data *data, struct rt_wdb *wdbp)
Definition: ptbl.h:62
#define DB_OPEN_READWRITE
Definition: raytrace.h:3555
int mk_nmg(struct rt_wdb *filep, const char *name, struct model *m)
Definition: nmg.c:41
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
COMPLEX data[64]
Definition: fftest.c:34
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#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 LOOKUP_QUIET
Definition: raytrace.h:893
#define RT_WDB_TYPE_DB_DISK
Definition: raytrace.h:1295
struct bu_ptbl * children
int mk_brep(struct rt_wdb *wdbp, const char *name, ON_Brep *brep)
Definition: brep.cpp:42
#define BN_TOL_DIST
Definition: tol.h:109
void db_close(struct db_i *dbip)
int nmg_mark_edges_real(const uint32_t *magic_p)
Definition: nmg_misc.c:846
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
Support for uniform tolerances.
Definition: tol.h:71
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
int main(int argc, char *argv[])
struct model * brep_to_nmg(struct subbrep_object_data *data, struct rt_wdb *wdbp)
struct nmgregion * nmg_mrsv(struct model *m)
Definition: nmg_mk.c:306
#define BU_PTBL_LEN(ptbl)
Definition: ptbl.h:107
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
void subbrep_object_free(struct subbrep_object_data *obj)
struct model * nmg_mm(void)
Definition: nmg_mk.c:235
int subbrep_split(struct subbrep_object_data *data)
void * idb_ptr
Definition: raytrace.h:195
int make_shape(struct subbrep_object_data *data, struct rt_wdb *wdbp)
#define DBI_NULL
Definition: raytrace.h:827
struct bu_vls * key
#define RT_DIR_NULL
Definition: raytrace.h:875
struct db_i * db_open(const char *name, const char *mode)
Definition: db_open.c:59
int idb_minor_type
ID_xxx.
Definition: raytrace.h:193
int db_dirbuild(struct db_i *dbip)
Definition: db5_scan.c:301
struct faceuse * nmg_cmface(struct shell *s, struct vertex ***verts, int n)
Definition: nmg_mod.c:979
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
Definition: vls.h:56
csg_object_params * params
int subbrep_to_csg_cylinder(struct subbrep_object_data *data, struct rt_wdb *wdbp)
struct rt_wdb * wdb_dbopen(struct db_i *dbip, int mode)
Definition: wdb.c:64
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
void nmg_region_a(struct nmgregion *r, const struct bn_tol *tol)
Definition: nmg_mk.c:2557