BRL-CAD
test_ssi.cpp
Go to the documentation of this file.
1 /* T E S T _ S S I . C P P
2  * BRL-CAD
3  *
4  * Copyright (c) 2013-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 
21 #include "common.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <iostream>
25 #include <assert.h>
26 #include "vmath.h"
27 #include "brep.h"
28 #include "raytrace.h"
29 
30 #include "rtgeom.h"
31 #include "wdb.h"
32 
33 int
34 get_surface(const char *name, struct db_i *dbip, struct rt_db_internal *intern, struct rt_brep_internal **brep_ip) {
35 
36  struct directory *dp;
37  (*brep_ip) = NULL;
38 
39 
40  dp = db_lookup(dbip, name, LOOKUP_QUIET);
41  if (dp == RT_DIR_NULL) {
42  bu_log("ERROR: Unable to look up object %s\n", name);
43  return -1;
44  }
45 
46  if (rt_db_get_internal(intern, dp, dbip, NULL, &rt_uniresource) < 0) {
47  bu_log("ERROR: Unable to get internal representation of %s\n", name);
48  return -1;
49  }
50 
51  RT_CK_DB_INTERNAL(intern);
52 
53  if (intern->idb_minor_type != DB5_MINORTYPE_BRLCAD_BREP) {
54  bu_log("ERROR: object %s does not appear to be of type BRep\n", name);
55  return -1;
56  } else {
57  (*brep_ip) = (struct rt_brep_internal *)(intern->idb_ptr);
58  }
59 
60  RT_BREP_CK_MAGIC(*brep_ip);
61  return 0;
62 }
63 
64 int
65 main(int argc, char** argv)
66 {
67  int ret = 0;
68  struct bu_vls intersect_name, name;
69 
70  if (argc != 6 && argc != 7) {
71  bu_log("Usage: %s %s\n", argv[0], "<file> <obj1> <obj2> <surf_i> <surf_j> [curve_name]");
72  return -1;
73  }
74 
75  // Read the file
76  struct db_i *dbip;
77  dbip = db_open(argv[1], DB_OPEN_READWRITE);
78  if (dbip == DBI_NULL) {
79  bu_log("ERROR: Unable to read from geometry database file %s\n", argv[1]);
80  return -1;
81  }
82 
83  if (db_dirbuild(dbip) < 0) {
84  bu_log("ERROR: Unable to read from %s\n", argv[1]);
85  return -1;
86  }
87 
88  // Get surfaces
89  struct rt_db_internal obj1_intern, obj2_intern;
90  struct rt_brep_internal *obj1_brep_ip = NULL, *obj2_brep_ip = NULL;
91 
92  RT_DB_INTERNAL_INIT(&obj1_intern);
93  RT_DB_INTERNAL_INIT(&obj2_intern);
94  if (get_surface(argv[2], dbip, &obj1_intern, &obj1_brep_ip)) return -1;
95  if (get_surface(argv[3], dbip, &obj2_intern, &obj2_brep_ip)) return -1;
96 
97  // Manipulate the openNURBS objects
98  ON_Brep *brep1 = obj1_brep_ip->brep;
99  ON_Brep *brep2 = obj2_brep_ip->brep;
100 
101  ON_NurbsSurface surf1;
102  ON_NurbsSurface surf2;
103 
104  int a = atoi(argv[4]), b = atoi(argv[5]);
105  if (a < 0 || a >= brep1->m_S.Count() || b < 0 || b >= brep2->m_S.Count()) {
106  bu_log("Out of range: \n");
107  bu_log("\t0 <= i <= %d\n", brep1->m_S.Count() - 1);
108  bu_log("\t0 <= j <= %d\n", brep2->m_S.Count() - 1);
109  return -1;
110  }
111 
112  brep1->m_S[a]->GetNurbForm(surf1);
113  brep2->m_S[b]->GetNurbForm(surf2);
114 
115  // Run the intersection
116  ON_ClassArray<ON_SSX_EVENT> events;
117  if (ON_Intersect(&surf1, &surf2, events) < 0) {
118  bu_log("Intersection failed\n");
119  return -1;
120  }
121 
122  bu_log("%d intersection segments.\n", events.Count());
123  if (events.Count() == 0)
124  return 0;
125 
126  bu_vls_init(&intersect_name);
127  if (argc == 7) {
128  bu_vls_sprintf(&intersect_name, "%s_", argv[6]);
129  } else {
130  bu_vls_sprintf(&intersect_name, "%s_%s_", argv[2], argv[3]);
131  }
132 
133  // Print the information of the intersection curves
134  bu_log("*** Intersection Events: ***\n");
135  for (int i = 0; i < events.Count(); i++) {
136  ON_wString wstr;
137  ON_TextLog textlog(wstr);
138  DumpSSXEvent(events[i], textlog);
139  ON_String str = ON_String(wstr);
140  bu_log("Intersection event %d:\n %s", i + 1, str.Array());
141  }
142 
143  for (int i = 0; i < events.Count() * 2; i++) {
144  struct rt_db_internal intern;
145  RT_DB_INTERNAL_INIT(&intern);
146  intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
147  switch (events[i%events.Count()].m_type) {
148  case ON_SSX_EVENT::ssx_overlap:
149  case ON_SSX_EVENT::ssx_tangent:
150  case ON_SSX_EVENT::ssx_transverse:
151  {
152  // curves
153  ON_Curve *curve2d = i < events.Count() ? events[i].m_curveA :
154  events[i - events.Count()].m_curveB;
155  ON_NurbsCurve *nurbscurve2d = ON_NurbsCurve::New();
156  curve2d->GetNurbForm(*nurbscurve2d);
157  // Use a sketch primitive to represent a 2D curve (polyline curve).
158  // The CVs of the curve are used as vertexes of the sketch.
159  struct rt_sketch_internal *sketch;
160  int vert_count = nurbscurve2d->CVCount();
161  intern.idb_type = ID_SKETCH;
162  intern.idb_meth = &OBJ[ID_SKETCH];
163  BU_ALLOC(intern.idb_ptr, struct rt_sketch_internal);
164  sketch = (struct rt_sketch_internal *)intern.idb_ptr;
165  sketch->magic = RT_SKETCH_INTERNAL_MAGIC;
166  VSET(sketch->V, 0.0, 0.0, 0.0);
167  VSET(sketch->u_vec, 1.0, 0.0, 0.0);
168  VSET(sketch->v_vec, 0.0, 1.0, 0.0);
169  sketch->vert_count = vert_count;
170  sketch->curve.count = vert_count - 1;
171 
172  // The memory must be dynamic allocated since they are bu_free'd
173  // in rt_db_free_internal()
174  sketch->verts = (point2d_t *)bu_calloc(vert_count, sizeof(point2d_t), "sketch->verts");
175  sketch->curve.reverse = (int *)bu_calloc(vert_count - 1, sizeof(int), "sketch->crv->reverse");
176  sketch->curve.segment = (void **)bu_calloc(vert_count - 1, sizeof(void *), "sketch->crv->segments");
177 
178  for (int j = 0; j < vert_count; j++) {
179  ON_3dPoint CV3d;
180  nurbscurve2d->GetCV(j, CV3d);
181  sketch->verts[j][0] = CV3d.x;
182  sketch->verts[j][1] = CV3d.y;
183  if (j != 0) {
184  struct line_seg *lsg;
185  BU_ALLOC(lsg, struct line_seg);
186  lsg->magic = CURVE_LSEG_MAGIC;
187  lsg->start = j - 1;
188  lsg->end = j;
189  sketch->curve.segment[j - 1] = (void *)lsg;
190  sketch->curve.reverse[j - 1] = 0;
191  }
192  }
193  break;
194  }
195  case ON_SSX_EVENT::ssx_tangent_point:
196  case ON_SSX_EVENT::ssx_transverse_point:
197  {
198  // use a sphere to display points
199  ON_3dPoint center = i < events.Count() ? events[i].m_pointA :
200  events[i - events.Count()].m_pointB;
201  double radius = 0.1;
202  struct rt_ell_internal* sph;
203  intern.idb_type = ID_SPH;
204  intern.idb_meth = &OBJ[ID_SPH];
205  BU_ALLOC(intern.idb_ptr, struct rt_ell_internal);
206  sph = (struct rt_ell_internal *)intern.idb_ptr;
207  sph->magic = RT_ELL_INTERNAL_MAGIC;
208  VSET(sph->v, center.x, center.y, center.z);
209  VSET(sph->a, radius, 0.0, 0.0);
210  VSET(sph->b, 0.0, radius, 0.0);
211  VSET(sph->c, 0.0, 0.0, radius);
212  break;
213  }
214  default:
215  break;
216  }
217 
218  bu_vls_init(&name);
219  bu_vls_sprintf(&name, "%s2d%c_%d", bu_vls_addr(&intersect_name),
220  i < events.Count() ? 'A' : 'B', i % events.Count());
221 
222  struct directory *dp;
223  dp = db_diradd(dbip, bu_vls_addr(&name), RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type);
224  ret = rt_db_put_internal(dp, dbip, &intern, &rt_uniresource);
225  if (ret)
226  bu_log("ERROR: failure writing [%s] to disk\n", dp->d_namep);
227  else
228  bu_log("%s is written to file.\n", dp->d_namep);
229  bu_vls_free(&name);
230  }
231 
232  for (int i = 0; i < events.Count(); i++) {
233  struct rt_db_internal intern;
234  RT_DB_INTERNAL_INIT(&intern);
235  intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
236  switch (events[i].m_type) {
237  case ON_SSX_EVENT::ssx_overlap:
238  case ON_SSX_EVENT::ssx_tangent:
239  case ON_SSX_EVENT::ssx_transverse:
240  {
241  // Use a pipe primitive to represent a curve.
242  // The CVs of the curve are used as vertexes of the pipe.
243  ON_Curve *curve3d = events[i].m_curve3d;
244  ON_NurbsCurve *nurbscurve3d = ON_NurbsCurve::New();
245  curve3d->GetNurbForm(*nurbscurve3d);
246  intern.idb_type = ID_PIPE;
247  intern.idb_meth = &OBJ[ID_PIPE];
248  BU_ALLOC(intern.idb_ptr, struct rt_pipe_internal);
249  struct rt_pipe_internal *pi;
250  pi = (struct rt_pipe_internal *)intern.idb_ptr;
251  pi->pipe_magic = RT_PIPE_INTERNAL_MAGIC;
252  pi->pipe_count = nurbscurve3d->CVCount();
253  BU_LIST_INIT(&(pi->pipe_segs_head));
254  struct wdb_pipept *ps;
255 
256  fastf_t od = nurbscurve3d->BoundingBox().Diagonal().Length() * 0.05;
257  for (int j = 0; j < nurbscurve3d->CVCount(); j++) {
258  BU_ALLOC(ps, struct wdb_pipept);
259  ps->l.magic = WDB_PIPESEG_MAGIC;
260  ps->l.back = NULL;
261  ps->l.forw = NULL;
262  ON_3dPoint p;
263  nurbscurve3d->GetCV(j, p);
264  VSET(ps->pp_coord, p.x, p.y, p.z);
265  ps->pp_id = 0.0;
266  ps->pp_od = od;
267  ps->pp_bendradius = 0;
268  BU_LIST_INSERT(&pi->pipe_segs_head, &ps->l);
269  }
270  break;
271  }
272  case ON_SSX_EVENT::ssx_tangent_point:
273  case ON_SSX_EVENT::ssx_transverse_point:
274  {
275  // use a sphere to display points
276  ON_3dPoint center = events[i].m_point3d;
277  double radius = 0.1;
278  struct rt_ell_internal* sph;
279  intern.idb_type = ID_SPH;
280  intern.idb_meth = &OBJ[ID_SPH];
281  BU_ALLOC(intern.idb_ptr, struct rt_ell_internal);
282  sph = (struct rt_ell_internal *)intern.idb_ptr;
283  sph->magic = RT_ELL_INTERNAL_MAGIC;
284  VSET(sph->v, center.x, center.y, center.z);
285  VSET(sph->a, radius, 0.0, 0.0);
286  VSET(sph->b, 0.0, radius, 0.0);
287  VSET(sph->c, 0.0, 0.0, radius);
288  break;
289  }
290  default:
291  break;
292  }
293 
294  bu_vls_init(&name);
295  bu_vls_sprintf(&name, "%s3d_%d", bu_vls_addr(&intersect_name), i);
296 
297  struct directory *dp;
298  dp = db_diradd(dbip, bu_vls_addr(&name), RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type);
299  ret = rt_db_put_internal(dp, dbip, &intern, &rt_uniresource);
300  if (ret)
301  bu_log("ERROR: failure writing [%s] to disk\n", dp->d_namep);
302  else
303  bu_log("%s is written to file.\n", dp->d_namep);
304  bu_vls_free(&name);
305  }
306 
307  bu_vls_free(&intersect_name);
308 
309  return ret;
310 }
311 
312 
313 // Local Variables:
314 // tab-width: 8
315 // mode: C++
316 // c-basic-offset: 4
317 // indent-tabs-mode: t
318 // c-file-style: "stroustrup"
319 // End:
320 // ex: shiftwidth=4 tabstop=8
void bu_vls_init(struct bu_vls *vp)
Definition: vls.c:56
char * d_namep
pointer to name string
Definition: raytrace.h:859
Definition: raytrace.h:800
bool ON_Intersect(const ON_3dPoint &pointA, const ON_3dPoint &pointB, ON_ClassArray< ON_PX_EVENT > &x, double tol)
Definition: intersect.cpp:647
int get_surface(const char *name, struct db_i *dbip, struct rt_db_internal *intern, struct rt_brep_internal **brep_ip)
Definition: test_ssi.cpp:34
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
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
#define ID_PIPE
Pipe (wire) solid.
Definition: raytrace.h:473
Definition: clone.c:90
#define VSET(a, b, c, d)
Definition: color.c:53
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
Header file for the BRL-CAD common definitions.
void DumpSSXEvent(ON_SSX_EVENT &x, ON_TextLog &text_log)
Definition: ssx_event.cpp:30
#define DB_OPEN_READWRITE
Definition: raytrace.h:3555
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 RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#define RT_ELL_INTERNAL_MAGIC
Definition: magic.h:91
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#define RT_DIR_SOLID
this name is a solid
Definition: raytrace.h:883
#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
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
#define ID_SPH
Sphere.
Definition: raytrace.h:468
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
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
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * idb_ptr
Definition: raytrace.h:195
const struct rt_functab OBJ[]
Definition: table.c:159
#define DBI_NULL
Definition: raytrace.h:827
#define WDB_PIPESEG_MAGIC
Definition: magic.h:214
#define RT_DIR_NULL
Definition: raytrace.h:875
#define RT_SKETCH_INTERNAL_MAGIC
Definition: magic.h:108
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
#define CURVE_LSEG_MAGIC
Definition: magic.h:199
int main(int argc, char **argv)
Definition: test_ssi.cpp:65
Definition: vls.h:56
double fastf_t
Definition: defines.h:300
#define ID_SKETCH
2D sketch
Definition: raytrace.h:484
#define RT_PIPE_INTERNAL_MAGIC
Definition: magic.h:104