BRL-CAD
revolve_brep.cpp
Go to the documentation of this file.
1 /* R E V O L V E _ B R E P . C P P
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 revolve_brep.cpp
21  *
22  * Convert a Revolved Sketch to b-rep form
23  *
24  */
25 
26 #include "common.h"
27 
28 #include "raytrace.h"
29 #include "rtgeom.h"
30 #include "nmg.h"
31 #include "brep.h"
32 
33 extern "C" {
34  extern void rt_sketch_brep(ON_Brep **bi, struct rt_db_internal *ip, const struct bn_tol *tol);
35 }
36 
37 
38 void FindLoops(ON_Brep **b, const ON_Line* revaxis, const fastf_t ang) {
39  ON_3dPoint ptmatch, ptterminate, pstart, pend;
40 
41  int *curvearray;
42  curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list"));
43  for (int i = 0; i < (*b)->m_C3.Count(); i++) {
44  curvearray[i] = -1;
45  }
46  ON_SimpleArray<ON_Curve *> allsegments;
47  ON_SimpleArray<ON_Curve *> loopsegments;
48  int loop_complete;
49  for (int i = 0; i < (*b)->m_C3.Count(); i++) {
50  allsegments.Append((*b)->m_C3[i]);
51  }
52 
53  int allcurvesassigned = 0;
54  int assignedcount = 0;
55  int curvecount = 0;
56  int loopcount = 0;
57  while (allcurvesassigned != 1) {
58  int havefirstcurve = 0;
59  while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) {
60  if (curvearray[curvecount] == -1) {
61  havefirstcurve = 1;
62  } else {
63  curvecount++;
64  }
65  }
66  // First, sort through things to assign curves to loops.
67  loop_complete = 0;
68  while ((loop_complete != 1) && (allcurvesassigned != 1)) {
69  curvearray[curvecount] = loopcount;
70  ptmatch = (*b)->m_C3[curvecount]->PointAtEnd();
71  ptterminate = (*b)->m_C3[curvecount]->PointAtStart();
72  for (int i = 0; i < allsegments.Count(); i++) {
73  pstart = (*b)->m_C3[i]->PointAtStart();
74  pend = (*b)->m_C3[i]->PointAtEnd();
75  if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) {
76  curvecount = i;
77  ptmatch = pend;
78  i = allsegments.Count();
79  if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) {
80  loop_complete = 1;
81  loopcount++;
82  }
83  } else {
84  if (i == allsegments.Count() - 1) {
85  loop_complete = 1; //If we reach this pass, loop had better be complete
86  loopcount++;
87  assignedcount = 0;
88  for (int j = 0; j < allsegments.Count(); j++) {
89  if (curvearray[j] != -1) assignedcount++;
90  }
91  if (allsegments.Count() == assignedcount) allcurvesassigned = 1;
92  }
93  }
94  }
95  }
96  }
97 
98  double maxdist = 0.0;
99  int largest_loop_index = 0;
100  for (int i = 0; i <= loopcount ; i++) {
101  ON_BoundingBox lbbox;
102  for (int j = 0; j < (*b)->m_C3.Count(); j++) {
103  if (curvearray[j] == i) {
104  ON_Curve *currcurve = (*b)->m_C3[j];
105  currcurve->GetBoundingBox(lbbox, true);
106  }
107  }
108  point_t minpt, maxpt;
109  double currdist;
110  VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]);
111  VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]);
112  currdist = DIST_PT_PT(minpt, maxpt);
113  if (currdist > maxdist) {
114  maxdist = currdist;
115  largest_loop_index = i;
116  }
117  }
118 
119  for (int i = 0; i < loopcount ; i++) {
120  ON_PolyCurve* poly_curve = new ON_PolyCurve();
121  for (int j = 0; j < allsegments.Count(); j++) {
122  if (curvearray[j] == i) {
123  poly_curve->Append(allsegments[j]);
124  }
125  }
126 
127  ON_NurbsCurve *revcurve = ON_NurbsCurve::New();
128  poly_curve->GetNurbForm(*revcurve);
129  ON_RevSurface* revsurf = ON_RevSurface::New();
130  revsurf->m_curve = revcurve;
131  revsurf->m_axis = *revaxis;
132  revsurf->m_angle = ON_Interval(0, ang);
133  ON_BrepFace *face = (*b)->NewFace(*revsurf);
134 
135  if (i == largest_loop_index) {
136  (*b)->FlipFace(*face);
137  }
138  }
139 
140  bu_free(curvearray, "sketch edge list");
141 }
142 
143 
144 extern "C" void
145 rt_revolve_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
146 {
147  struct rt_db_internal *tmp_internal;
148  struct rt_revolve_internal *rip;
149  struct rt_sketch_internal *eip;
150 
151  BU_ALLOC(tmp_internal, struct rt_db_internal);
152  RT_DB_INTERNAL_INIT(tmp_internal);
153 
154  rip = (struct rt_revolve_internal *)ip->idb_ptr;
155  RT_REVOLVE_CK_MAGIC(rip);
156  eip = rip->skt;
157  RT_SKETCH_CK_MAGIC(eip);
158 
159  ON_3dPoint plane_origin;
160  ON_3dVector plane_x_dir, plane_y_dir;
161 
162  bool full_revolve = true;
163  if (rip->ang < 2*ON_PI && rip->ang > 0)
164  full_revolve = false;
165 
166  // Find plane in 3 space corresponding to the sketch.
167 
168  vect_t startpoint;
169  VADD2(startpoint, rip->v3d, rip->r);
170  plane_origin = ON_3dPoint(startpoint);
171  plane_x_dir = ON_3dVector(eip->u_vec);
172  plane_y_dir = ON_3dVector(eip->v_vec);
173  const ON_Plane sketch_plane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
174 
175  // For the brep, need the list of 3D vertex points. In sketch, they
176  // are stored as 2D coordinates, so use the sketch_plane to define 3 space
177  // points for the vertices.
178  for (size_t i = 0; i < eip->vert_count; i++) {
179  (*b)->NewVertex(sketch_plane.PointAt(eip->verts[i][0], eip->verts[i][1]), 0.0);
180  }
181 
182  // Create the brep elements corresponding to the sketch lines, curves
183  // and bezier segments. Create 2d, 3d and BrepEdge elements for each segment.
184  // Will need to use the bboxes of each element to
185  // build the overall bounding box for the face. Use bGrowBox to expand
186  // a single box.
187  struct line_seg *lsg;
188  struct carc_seg *csg;
189  struct bezier_seg *bsg;
190  uint32_t *lng;
191  for (size_t i = 0; i < (&eip->curve)->count; i++) {
192  lng = (uint32_t *)(&eip->curve)->segment[i];
193  switch (*lng) {
194  case CURVE_LSEG_MAGIC: {
195  lsg = (struct line_seg *)lng;
196  ON_Curve* lsg3d = new ON_LineCurve((*b)->m_V[lsg->start].Point(), (*b)->m_V[lsg->end].Point());
197  lsg3d->SetDomain(0.0, 1.0);
198  (*b)->m_C3.Append(lsg3d);
199  }
200  break;
201  case CURVE_CARC_MAGIC:
202  csg = (struct carc_seg *)lng;
203  if (csg->radius < 0) { {
204  ON_3dPoint cntrpt = (*b)->m_V[csg->end].Point();
205  ON_3dPoint edgept = (*b)->m_V[csg->start].Point();
206  ON_Plane cplane = ON_Plane(cntrpt, plane_x_dir, plane_y_dir);
207  ON_Circle c3dcirc = ON_Circle(cplane, cntrpt.DistanceTo(edgept));
208  ON_Curve* c3d = new ON_ArcCurve((const ON_Circle)c3dcirc);
209  c3d->SetDomain(0.0, 1.0);
210  (*b)->m_C3.Append(c3d);
211  }
212  } else {
213  // need to calculated 3rd point on arc - look to sketch.c around line 581 for
214  // logic
215  }
216  break;
217  case CURVE_BEZIER_MAGIC:
218  bsg = (struct bezier_seg *)lng;
219  {
220  ON_3dPointArray bezpoints = ON_3dPointArray(bsg->degree + 1);
221  for (int j = 0; j < bsg->degree + 1; j++) {
222  bezpoints.Append((*b)->m_V[bsg->ctl_points[j]].Point());
223  }
224  ON_BezierCurve bez3d = ON_BezierCurve((const ON_3dPointArray)bezpoints);
225  ON_NurbsCurve* beznurb3d = ON_NurbsCurve::New();
226  bez3d.GetNurbForm(*beznurb3d);
227  beznurb3d->SetDomain(0.0, 1.0);
228  (*b)->m_C3.Append(beznurb3d);
229  }
230  break;
231  default:
232  bu_log("Unhandled sketch object\n");
233  break;
234  }
235  }
236 
237  vect_t endpoint;
238  VADD2(endpoint, rip->v3d, rip->axis3d);
239  const ON_Line& revaxis = ON_Line(ON_3dPoint(rip->v3d), ON_3dPoint(endpoint));
240 
241  FindLoops(b, &revaxis, rip->ang);
242 
243  // Create the two boundary surfaces, if it's not a full revolution
244  if (!full_revolve) {
245  // First, deduce the transformation matrices to calculate the position of the end surface
246  // The transformation matrices are to rotate an arbitrary point around an arbitrary axis
247  // Let the point A = (x, y, z), the rotation axis is p1p2 = (x2,y2,z2)-(x1,y1,z1) = (a,b,c)
248  // Then T1 is to translate p1 to the origin
249  // Rx is to rotate p1p2 around the X axis to the plane XOZ
250  // Ry is to rotate p1p2 around the Y axis to be coincident to Z axis
251  // Rz is to rotate A with the angle around Z axis (the new p1p2)
252  // RxInv, RyInv, T1Inv are the inverse transformation of Rx, Ry, T1, respectively.
253  // The whole transformation is A' = A*T1*Rx*Ry*Rz*Ry*Inv*Rx*Inv = A*R
254  vect_t end_plane_origin, end_plane_x_dir, end_plane_y_dir;
255  mat_t R;
256  MAT_IDN(R);
257  mat_t T1, Rx, Ry, Rz, RxInv, RyInv, T1Inv;
258  MAT_IDN(T1);
259  VSET(&T1[12], -rip->v3d[0], -rip->v3d[1], -rip->v3d[2]);
260  MAT_IDN(Rx);
261  fastf_t v = sqrt(rip->axis3d[1]*rip->axis3d[1]+rip->axis3d[2]*rip->axis3d[2]);
262  VSET(&Rx[4], 0, rip->axis3d[2]/v, rip->axis3d[1]/v);
263  VSET(&Rx[8], 0, -rip->axis3d[1]/v, rip->axis3d[2]/v);
264  MAT_IDN(Ry);
265  fastf_t u = MAGNITUDE(rip->axis3d);
266  VSET(&Ry[0], v/u, 0, -rip->axis3d[0]/u);
267  VSET(&Ry[8], rip->axis3d[0]/u, 0, v/u);
268  MAT_IDN(Rz);
269  fastf_t C, S;
270  C = cos(rip->ang);
271  S = sin(rip->ang);
272  VSET(&Rz[0], C, S, 0);
273  VSET(&Rz[4], -S, C, 0);
274  bn_mat_inv(RxInv, Rx);
275  bn_mat_inv(RyInv, Ry);
276  bn_mat_inv(T1Inv, T1);
277  mat_t temp;
278  bn_mat_mul4(temp, T1, Rx, Ry, Rz);
279  bn_mat_mul4(R, temp, RyInv, RxInv, T1Inv);
280  VEC3X3MAT(end_plane_origin, plane_origin, R);
281  VADD2(end_plane_origin, end_plane_origin, &R[12]);
282  VEC3X3MAT(end_plane_x_dir, plane_x_dir, R);
283  VEC3X3MAT(end_plane_y_dir, plane_y_dir, R);
284 
285  // Create the start and end surface with rt_sketch_brep()
286  struct rt_sketch_internal sketch;
287  sketch = *(rip->skt);
288  ON_Brep *b1 = ON_Brep::New();
289  VMOVE(sketch.V, plane_origin);
290  VMOVE(sketch.u_vec, plane_x_dir);
291  VMOVE(sketch.v_vec, plane_y_dir);
292  tmp_internal->idb_ptr = (void *)(&sketch);
293  rt_sketch_brep(&b1, tmp_internal, tol);
294  (*b)->Append(*b1->Duplicate());
295 
296  ON_Brep *b2 = ON_Brep::New();
297  VMOVE(sketch.V, end_plane_origin);
298  VMOVE(sketch.u_vec, end_plane_x_dir);
299  VMOVE(sketch.v_vec, end_plane_y_dir);
300  tmp_internal->idb_ptr = (void *)(&sketch);
301  rt_sketch_brep(&b2, tmp_internal, tol);
302  (*b)->Append(*b2->Duplicate());
303  (*b)->FlipFace((*b)->m_F[(*b)->m_F.Count()-1]);
304  }
305  bu_free(tmp_internal, "free temporary rt_db_internal");
306 }
307 
308 
309 // Local Variables:
310 // tab-width: 8
311 // mode: C++
312 // c-basic-offset: 4
313 // indent-tabs-mode: t
314 // c-file-style: "stroustrup"
315 // End:
316 // ex: shiftwidth=4 tabstop=8
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
fastf_t C[2 *MAX_CNT+1][2 *MAX_CNT+1]
Definition: dsp_brep.cpp:38
#define VSET(a, b, c, d)
Definition: color.c:53
void rt_revolve_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
#define CURVE_CARC_MAGIC
Definition: magic.h:198
Header file for the BRL-CAD common definitions.
void bn_mat_mul4(mat_t o, const mat_t a, const mat_t b, const mat_t c, const mat_t d)
Definition: mat.c:166
#define CURVE_BEZIER_MAGIC
Definition: magic.h:197
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
void FindLoops(ON_Brep **b, const ON_Line *revaxis, const fastf_t ang)
void rt_sketch_brep(ON_Brep **bi, struct rt_db_internal *ip, const struct bn_tol *tol)
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
void bn_mat_inv(mat_t output, const mat_t input)
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
Support for uniform tolerances.
Definition: tol.h:71
void * idb_ptr
Definition: raytrace.h:195
#define R
Definition: msr.c:55
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define CURVE_LSEG_MAGIC
Definition: magic.h:199
double fastf_t
Definition: defines.h:300