BRL-CAD
pipe_brep.cpp
Go to the documentation of this file.
1 /* P I P 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 pipe_brep.cpp
21  *
22  * Convert a Pipe to b-rep form
23  *
24  */
25 
26 #include "common.h"
27 
28 #include "raytrace.h"
29 #include "rtgeom.h"
30 #include "brep.h"
31 #include "wdb.h"
32 
33 
34 void
35 generate_curves(fastf_t id, fastf_t od, ON_Plane *plane, ON_SimpleArray<ON_Curve*> *outer, ON_SimpleArray<ON_Curve*> *inner)
36 {
37  ON_Circle outercirclestart = ON_Circle(*plane, od/2.0);
38  ON_NurbsCurve *ocurve = ON_NurbsCurve::New();
39  outercirclestart.GetNurbForm(*ocurve);
40  outer->Append(ON_Curve::Cast(ocurve));
41  if (id > 0.0) {
42  ON_Circle innercirclestart = ON_Circle(*plane, id/2.0);
43  ON_NurbsCurve *icurve = ON_NurbsCurve::New();
44  innercirclestart.GetNurbForm(*icurve);
45  inner->Append(ON_Curve::Cast(icurve));
46  }
47 }
48 
49 
50 void
51 make_linear_surfaces(ON_Brep **b, ON_SimpleArray<ON_Curve*> *startoutercurves, ON_SimpleArray<ON_Curve*> *endoutercurves, ON_SimpleArray<ON_Curve*> *startinnercurves, ON_SimpleArray<ON_Curve*> *endinnercurves)
52 {
53  int c1ind = (*b)->AddEdgeCurve((*startoutercurves)[0]);
54  int c2ind = (*b)->AddEdgeCurve((*endoutercurves)[0]);
55  ON_BrepVertex& vert1 = (*b)->NewVertex((*b)->m_C3[c1ind]->PointAt(0), SMALL_FASTF);
56  vert1.m_tolerance = 0.0;
57  int vert1ind = (*b)->m_V.Count() - 1;
58  ON_BrepVertex& vert2 = (*b)->NewVertex((*b)->m_C3[c2ind]->PointAt(0), SMALL_FASTF);
59  vert2.m_tolerance = 0.0;
60  int vert2ind = (*b)->m_V.Count() - 1;
61  ON_BrepEdge* startedge = &(*b)->NewEdge((*b)->m_V[vert1ind], (*b)->m_V[vert1ind], c1ind);
62  startedge->m_tolerance = 0.0;
63  ON_BrepEdge* endedge = &(*b)->NewEdge((*b)->m_V[vert2ind], (*b)->m_V[vert2ind], c2ind);
64  endedge->m_tolerance = 0.0;
65  // startedge might point to the wrong place if adding endedge expands the capacity
66  // of the edge array, so we need to fix it.
67  startedge = (*b)->Edge(startedge->m_edge_index);
68  startoutercurves->Empty();
69  for (int i = 0; i < endoutercurves->Count(); i++) {
70  ON_Curve *curve = (*endoutercurves)[i]->Duplicate();
71  startoutercurves->Append(curve);
72  }
73  ON_BrepFace *newouterface = (*b)->NewRuledFace(*startedge, false, *endedge, false);
74  if (newouterface != NULL) (*b)->FlipFace(*newouterface);
75 
76  if (startinnercurves->Count() > 0) {
77  int c3ind = (*b)->AddEdgeCurve(ON_Curve::Cast(*(startinnercurves[0])));
78  int c4ind = (*b)->AddEdgeCurve(ON_Curve::Cast(*(endinnercurves[0])));
79  ON_BrepVertex& vert3 = (*b)->NewVertex((*b)->m_C3[c3ind]->PointAt(0), SMALL_FASTF);
80  vert3.m_tolerance = 0.0;
81  int vert3ind = (*b)->m_V.Count() - 1;
82  ON_BrepVertex& vert4 = (*b)->NewVertex((*b)->m_C3[c4ind]->PointAt(0), SMALL_FASTF);
83  vert4.m_tolerance = 0.0;
84  int vert4ind = (*b)->m_V.Count() - 1;
85  ON_BrepEdge* startinneredge = &(*b)->NewEdge((*b)->m_V[vert3ind], (*b)->m_V[vert3ind], c3ind);
86  startinneredge->m_tolerance = 0.0;
87  ON_BrepEdge* endinneredge = &(*b)->NewEdge((*b)->m_V[vert4ind], (*b)->m_V[vert4ind], c4ind);
88  endinneredge->m_tolerance = 0.0;
89  startedge = (*b)->Edge(startedge->m_edge_index);
90  (*b)->NewRuledFace(*startinneredge, false, *endinneredge, false);
91  }
92  startinnercurves->Empty();
93  for (int i = 0; i < endinnercurves->Count(); i++) {
94  ON_Curve *curve = (*endinnercurves)[i]->Duplicate();
95  startinnercurves->Append(curve);
96  }
97 }
98 
99 
100 void
101 make_curved_surfaces(ON_Brep **b, ON_SimpleArray<ON_Curve*> *startoutercurves, ON_SimpleArray<ON_Curve*> *startinnercurves, fastf_t angle, point_t bend_center, vect_t norm)
102 {
103  point_t rev;
104  VADD2(rev, bend_center, norm);
105 
106  ON_Line revaxis = ON_Line(ON_3dPoint(bend_center), ON_3dPoint(rev));
107  ON_RevSurface* revsurf = ON_RevSurface::New();
108  revsurf->m_curve = *startoutercurves[0];
109  revsurf->m_axis = revaxis;
110  revsurf->m_angle = ON_Interval(2*ON_PI - angle, 2*ON_PI);
111  ON_BrepFace *face = (*b)->NewFace(*revsurf);
112  (*b)->FlipFace(*face);
113 
114  if (startinnercurves->Count() > 0) {
115  revsurf = ON_RevSurface::New();
116  revsurf->m_curve = *startinnercurves[0];
117  revsurf->m_axis = revaxis;
118  revsurf->m_angle = ON_Interval(2*ON_PI - angle, 2*ON_PI);
119  (void)(*b)->NewFace(*revsurf);
120  }
121 }
122 
123 
124 extern "C" void
125 rt_pipe_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *UNUSED(tol))
126 {
127  struct rt_pipe_internal *pip;
128 
129  register struct wdb_pipept *prevp;
130  register struct wdb_pipept *curp;
131  register struct wdb_pipept *nextp;
132  point_t current_point;
133  vect_t x_dir, y_dir, pipe_dir;
134 
135  ON_SimpleArray<ON_Curve*> startoutercurves;
136  ON_SimpleArray<ON_Curve*> startinnercurves;
137 
138  ON_SimpleArray<ON_Curve*> endoutercurves;
139  ON_SimpleArray<ON_Curve*> endinnercurves;
140 
141  ON_3dPoint plane_origin;
142  ON_3dVector plane_x_dir, plane_y_dir;
143 
144  ON_Plane endplane;
145  ON_BrepLoop *bloop;
146 
147  RT_CK_DB_INTERNAL(ip);
148  pip = (struct rt_pipe_internal *)ip->idb_ptr;
149  RT_PIPE_CK_MAGIC(pip);
150 
151  // delete duplicated points
152  curp = BU_LIST_FIRST(wdb_pipept, &pip->pipe_segs_head);
153  while (!(BU_LIST_NEXT_IS_HEAD(&curp->l, &pip->pipe_segs_head))) {
154  vect_t delta;
155  nextp = BU_LIST_NEXT(wdb_pipept, &curp->l);
156  VSUB2(delta, curp->pp_coord, nextp->pp_coord);
157  if (VNEAR_ZERO(delta, RT_LEN_TOL)) {
158  prevp = curp;
159  curp = BU_LIST_NEXT(wdb_pipept, &curp->l);
160  BU_LIST_DEQUEUE(&prevp->l);
161  } else {
162  curp = BU_LIST_NEXT(wdb_pipept, &curp->l);
163  }
164  }
165 
166  // make the first plane surface
167  if (BU_LIST_IS_EMPTY(&pip->pipe_segs_head)) return;
168  prevp = BU_LIST_FIRST(wdb_pipept, &pip->pipe_segs_head);
169  curp = BU_LIST_NEXT(wdb_pipept, &prevp->l);
170  nextp = BU_LIST_NEXT(wdb_pipept, &curp->l);
171  if (BU_LIST_IS_HEAD(&curp->l, &pip->pipe_segs_head)) return;
172 
173  VMOVE(current_point, curp->pp_coord);
174 
175  VSUB2(pipe_dir, prevp->pp_coord, curp->pp_coord);
176  bn_vec_ortho(x_dir, pipe_dir);
177  VCROSS(y_dir, pipe_dir, x_dir);
178  VUNITIZE(y_dir);
179 
180  plane_origin = ON_3dPoint(prevp->pp_coord);
181  plane_x_dir = ON_3dVector(x_dir);
182  plane_y_dir = ON_3dVector(y_dir);
183  endplane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
184 
185  generate_curves(prevp->pp_id, prevp->pp_od, &endplane, &endoutercurves, &endinnercurves);
186 
187  ON_PlaneSurface* bp = new ON_PlaneSurface();
188  bp->m_plane = endplane;
189  bp->SetDomain(0, -100.0, 100.0);
190  bp->SetDomain(1, -100.0, 100.0);
191  bp->SetExtents(0, bp->Domain(0));
192  bp->SetExtents(1, bp->Domain(1));
193  (*b)->m_S.Append(bp);
194  const int bsi = (*b)->m_S.Count() - 1;
195  ON_BrepFace& bface = (*b)->NewFace(bsi);
196  startoutercurves.Empty();
197  startinnercurves.Empty();
198  for (int i = 0; i < endoutercurves.Count(); i++) {
199  ON_Curve *curve = endoutercurves[i];
200  startoutercurves.Append(curve);
201  }
202  for (int i = 0; i < endinnercurves.Count(); i++) {
203  ON_Curve *curve = endinnercurves[i];
204  startinnercurves.Append(curve);
205  }
206 
207  (*b)->NewPlanarFaceLoop(bface.m_face_index, ON_BrepLoop::outer, endoutercurves, true);
208  bloop = (*b)->m_L.Last();
209  bp->SetDomain(0, bloop->m_pbox.m_min.x, bloop->m_pbox.m_max.x);
210  bp->SetDomain(1, bloop->m_pbox.m_min.y, bloop->m_pbox.m_max.y);
211  bp->SetExtents(0, bp->Domain(0));
212  bp->SetExtents(1, bp->Domain(1));
213  if (prevp->pp_id > 0.0) {
214  (*b)->NewPlanarFaceLoop(bface.m_face_index, ON_BrepLoop::inner, endinnercurves, true);
215  }
216  (*b)->SetTrimIsoFlags(bface);
217 
218  while (1) {
219  vect_t n1, n2;
220  vect_t norm;
221  fastf_t angle;
222  fastf_t dist_to_bend;
223  endoutercurves.Empty();
224  endinnercurves.Empty();
225 
226  if (BU_LIST_IS_HEAD(&nextp->l, &pip->pipe_segs_head)) {
227  // last segment, always linear
228  VSUB2(pipe_dir, prevp->pp_coord, curp->pp_coord);
229  bn_vec_ortho(x_dir, pipe_dir);
230  VCROSS(y_dir, pipe_dir, x_dir);
231  VUNITIZE(y_dir);
232  plane_origin = ON_3dPoint(curp->pp_coord);
233  plane_x_dir = ON_3dVector(x_dir);
234  plane_y_dir = ON_3dVector(y_dir);
235  endplane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
236  generate_curves(curp->pp_id, curp->pp_od, &endplane, &endoutercurves, &endinnercurves);
237  make_linear_surfaces(b, &startoutercurves, &endoutercurves, &startinnercurves, &endinnercurves);
238  break;
239  }
240 
241  VSUB2(n1, prevp->pp_coord, curp->pp_coord);
242  if (!(VNEAR_ZERO(n1, RT_LEN_TOL))) {
243  // isn't duplicate point, proceed
244  VSUB2(n2, nextp->pp_coord, curp->pp_coord);
245  VCROSS(norm, n1, n2);
246  VUNITIZE(n1);
247  VUNITIZE(n2);
248  angle = M_PI - acos(VDOT(n1, n2));
249  dist_to_bend = curp->pp_bendradius * tan(angle/2.0);
250 
251  if (isnan(dist_to_bend) || VNEAR_ZERO(norm, SQRT_SMALL_FASTF) || NEAR_ZERO(dist_to_bend, SQRT_SMALL_FASTF)) {
252  // points are collinear, treat as linear segment
253  VSUB2(pipe_dir, current_point, curp->pp_coord);
254  bn_vec_ortho(x_dir, pipe_dir);
255  VCROSS(y_dir, pipe_dir, x_dir);
256  VUNITIZE(y_dir);
257  plane_origin = ON_3dPoint(curp->pp_coord);
258  plane_x_dir = ON_3dVector(x_dir);
259  plane_y_dir = ON_3dVector(y_dir);
260  endplane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
261  generate_curves(curp->pp_id, curp->pp_od, &endplane, &endoutercurves, &endinnercurves);
262  make_linear_surfaces(b, &startoutercurves, &endoutercurves, &startinnercurves, &endinnercurves);
263  VMOVE(current_point, curp->pp_coord);
264  } else {
265  point_t bend_center;
266  point_t bend_start;
267  point_t bend_end;
268  vect_t v1;
269 
270  VUNITIZE(norm);
271 
272  // Linear part first
273  VJOIN1(bend_start, curp->pp_coord, dist_to_bend, n1);
274  VSUB2(pipe_dir, prevp->pp_coord, curp->pp_coord);
275  bn_vec_ortho(x_dir, pipe_dir);
276  VCROSS(y_dir, pipe_dir, x_dir);
277  VUNITIZE(y_dir);
278  plane_origin = ON_3dPoint(bend_start);
279  plane_x_dir = ON_3dVector(x_dir);
280  plane_y_dir = ON_3dVector(y_dir);
281  endplane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
282  generate_curves(curp->pp_id, curp->pp_od, &endplane, &endoutercurves, &endinnercurves);
283  make_linear_surfaces(b, &startoutercurves, &endoutercurves, &startinnercurves, &endinnercurves);
284 
285  // Now do curved section
286  VJOIN1(bend_end, curp->pp_coord, dist_to_bend, n2);
287  VCROSS(v1, n1, norm);
288  VJOIN1(bend_center, bend_start, -curp->pp_bendradius, v1);
289  make_curved_surfaces(b, &startoutercurves, &startinnercurves, angle, bend_center, norm);
290  startinnercurves.Empty();
291  startoutercurves.Empty();
292  VSUB2(pipe_dir, curp->pp_coord, nextp->pp_coord);
293  bn_vec_ortho(x_dir, pipe_dir);
294  VCROSS(y_dir, pipe_dir, x_dir);
295  VUNITIZE(y_dir);
296  plane_origin = ON_3dPoint(bend_end);
297  plane_x_dir = ON_3dVector(x_dir);
298  plane_y_dir = ON_3dVector(y_dir);
299  endplane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
300  generate_curves(curp->pp_id, curp->pp_od, &endplane, &startoutercurves, &startinnercurves);
301 
302  VMOVE(current_point, bend_end);
303  }
304  }
305  prevp = curp;
306  curp = nextp;
307  nextp = BU_LIST_NEXT(wdb_pipept, &curp->l);
308  }
309  // In the case of the final segment, also create the end face.
310  endoutercurves.Empty();
311  endinnercurves.Empty();
312 
313  VSUB2(pipe_dir, curp->pp_coord, prevp->pp_coord);
314  bn_vec_ortho(x_dir, pipe_dir);
315  VCROSS(y_dir, pipe_dir, x_dir);
316  VUNITIZE(y_dir);
317  plane_origin = ON_3dPoint(curp->pp_coord);
318  plane_x_dir = ON_3dVector(x_dir);
319  plane_y_dir = ON_3dVector(y_dir);
320  endplane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
321 
322  generate_curves(curp->pp_id, curp->pp_od, &endplane, &endoutercurves, &endinnercurves);
323 
324  ON_PlaneSurface* ebp = new ON_PlaneSurface();
325  ebp->m_plane = endplane;
326  ebp->SetDomain(0, -100.0, 100.0);
327  ebp->SetDomain(1, -100.0, 100.0);
328  ebp->SetExtents(0, bp->Domain(0));
329  ebp->SetExtents(1, bp->Domain(1));
330  (*b)->m_S.Append(ebp);
331  const int ebsi = (*b)->m_S.Count() - 1;
332  ON_BrepFace& ebface = (*b)->NewFace(ebsi);
333  (*b)->NewPlanarFaceLoop(ebface.m_face_index, ON_BrepLoop::outer, endoutercurves, true);
334  const ON_BrepLoop* ebloop = (*b)->m_L.Last();
335  ebp->SetDomain(0, ebloop->m_pbox.m_min.x, ebloop->m_pbox.m_max.x);
336  ebp->SetDomain(1, ebloop->m_pbox.m_min.y, ebloop->m_pbox.m_max.y);
337  ebp->SetExtents(0, ebp->Domain(0));
338  ebp->SetExtents(1, ebp->Domain(1));
339  if (prevp->pp_id > 0.0) {
340  (*b)->NewPlanarFaceLoop(ebface.m_face_index, ON_BrepLoop::inner, endinnercurves, true);
341  }
342  (*b)->SetTrimIsoFlags(ebface);
343 }
344 
345 
346 // Local Variables:
347 // tab-width: 8
348 // mode: C++
349 // c-basic-offset: 4
350 // indent-tabs-mode: t
351 // c-file-style: "stroustrup"
352 // End:
353 // ex: shiftwidth=4 tabstop=8
#define RT_LEN_TOL
Definition: raytrace.h:169
void make_linear_surfaces(ON_Brep **b, ON_SimpleArray< ON_Curve * > *startoutercurves, ON_SimpleArray< ON_Curve * > *endoutercurves, ON_SimpleArray< ON_Curve * > *startinnercurves, ON_SimpleArray< ON_Curve * > *endinnercurves)
Definition: pipe_brep.cpp:51
void rt_pipe_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
Definition: pipe_brep.cpp:125
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
#define M_PI
Definition: fft.h:35
void generate_curves(fastf_t id, fastf_t od, ON_Plane *plane, ON_SimpleArray< ON_Curve * > *outer, ON_SimpleArray< ON_Curve * > *inner)
Definition: pipe_brep.cpp:35
#define SMALL_FASTF
Definition: defines.h:342
Header file for the BRL-CAD common definitions.
#define BU_LIST_IS_HEAD(p, hp)
Definition: list.h:322
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
unsigned char * bp
Definition: rot.c:56
#define SQRT_SMALL_FASTF
Definition: defines.h:346
#define UNUSED(parameter)
Definition: common.h:239
void make_curved_surfaces(ON_Brep **b, ON_SimpleArray< ON_Curve * > *startoutercurves, ON_SimpleArray< ON_Curve * > *startinnercurves, fastf_t angle, point_t bend_center, vect_t norm)
Definition: pipe_brep.cpp:101
Support for uniform tolerances.
Definition: tol.h:71
void * idb_ptr
Definition: raytrace.h:195
void bn_vec_ortho(vect_t out, const vect_t in)
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
#define BU_LIST_NEXT_IS_HEAD(p, hp)
Definition: list.h:338
HIDDEN const point_t delta
Definition: sh_prj.c:618
double fastf_t
Definition: defines.h:300
#define BU_LIST_NEXT(structure, hp)
Definition: list.h:316
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312