BRL-CAD
sketch_brep.cpp
Go to the documentation of this file.
1 /* S K E T C H _ 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 sketch_brep.cpp
21  *
22  * Convert a sketch to b-rep form (does not create a solid brep)
23  *
24  */
25 
26 #include "common.h"
27 
28 #include "raytrace.h"
29 #include "rtgeom.h"
30 #include "brep.h"
31 
32 void FindLoops(ON_Brep **b) {
33  ON_3dPoint ptmatch, ptterminate, pstart, pend;
34  int *curvearray;
35  curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list"));
36  for (int i = 0; i < (*b)->m_C3.Count(); i++) {
37  curvearray[i] = -1;
38  }
39  ON_SimpleArray<ON_Curve *> allsegments;
40  ON_SimpleArray<ON_Curve *> loopsegments;
41  int loop_complete;
42  for (int i = 0; i < (*b)->m_C3.Count(); i++) {
43  allsegments.Append((*b)->m_C3[i]);
44  }
45 
46  int allcurvesassigned = 0;
47  int assignedcount = 0;
48  int curvecount = 0;
49  int loopcount = 0;
50  while (allcurvesassigned != 1) {
51  int havefirstcurve = 0;
52  while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) {
53  if (curvearray[curvecount] == -1) {
54  havefirstcurve = 1;
55  } else {
56  curvecount++;
57  }
58  }
59  // First, sort through things to assign curves to loops.
60  loop_complete = 0;
61  while ((loop_complete != 1) && (allcurvesassigned != 1)) {
62  curvearray[curvecount] = loopcount;
63  ptmatch = (*b)->m_C3[curvecount]->PointAtEnd();
64  ptterminate = (*b)->m_C3[curvecount]->PointAtStart();
65  for (int i = 0; i < allsegments.Count(); i++) {
66  pstart = (*b)->m_C3[i]->PointAtStart();
67  pend = (*b)->m_C3[i]->PointAtEnd();
68  if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) {
69  curvecount = i;
70  ptmatch = pend;
71  i = allsegments.Count();
72  if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) {
73  loop_complete = 1;
74  loopcount++;
75  }
76  } else {
77  if (i == allsegments.Count() - 1) {
78  loop_complete = 1; //If we reach this pass, loop had better be complete
79  loopcount++;
80  assignedcount = 0;
81  for (int j = 0; j < allsegments.Count(); j++) {
82  if (curvearray[j] != -1) assignedcount++;
83  }
84  if (allsegments.Count() == assignedcount) allcurvesassigned = 1;
85  }
86  }
87  }
88  }
89  }
90 
91  double maxdist = 0.0;
92  int largest_loop_index = 0;
93  for (int i = 0; i <= loopcount ; i++) {
94  ON_BoundingBox lbbox;
95  for (int j = 0; j < (*b)->m_C3.Count(); j++) {
96  if (curvearray[j] == i) {
97  ON_Curve *currcurve = (*b)->m_C3[j];
98  currcurve->GetBoundingBox(lbbox, true);
99  }
100  }
101  point_t minpt, maxpt;
102  double currdist;
103  VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]);
104  VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]);
105  currdist = DIST_PT_PT(minpt, maxpt);
106  if (currdist > maxdist) {
107  maxdist = currdist;
108  largest_loop_index = i;
109  }
110  }
111 
112 
113  for (int i = 0; i < allsegments.Count(); i++) {
114  if (curvearray[i] == largest_loop_index) loopsegments.Append((*b)->m_C3[i]);
115  }
116 
117  (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::outer, loopsegments, true);
118 
119  loopsegments.Empty();
120 
121  // If there's anything left, make inner loops out of it
122  for (int i = 0; i <= loopcount; i++) {
123  if (i != largest_loop_index) {
124  for (int j = 0; j < allsegments.Count(); j++) {
125  if (curvearray[j] == i) loopsegments.Append((*b)->m_C3[j]);
126  }
127  (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::inner, loopsegments, true);
128  }
129  loopsegments.Empty();
130  }
131 
132  bu_free(curvearray, "sketch edge list");
133 }
134 
135 
136 extern "C" void
137 rt_sketch_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *UNUSED(tol))
138 {
139  struct rt_sketch_internal *eip;
140 
141  RT_CK_DB_INTERNAL(ip);
142  eip = (struct rt_sketch_internal *)ip->idb_ptr;
143  RT_SKETCH_CK_MAGIC(eip);
144 
145  ON_3dPoint plane_origin;
146  ON_3dVector plane_x_dir, plane_y_dir;
147 
148  // Find plane in 3 space corresponding to the sketch.
149 
150  plane_origin = ON_3dPoint(eip->V);
151  plane_x_dir = ON_3dVector(eip->u_vec);
152  plane_y_dir = ON_3dVector(eip->v_vec);
153  const ON_Plane sketch_plane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir);
154 
155  // For the brep, need the list of 3D vertex points. In sketch, they
156  // are stored as 2D coordinates, so use the sketch_plane to define 3 space
157  // points for the vertices.
158  for (size_t i = 0; i < eip->vert_count; i++) {
159  (*b)->NewVertex(sketch_plane.PointAt(eip->verts[i][0], eip->verts[i][1]), 0.0);
160  }
161 
162  // Create the brep elements corresponding to the sketch lines, curves
163  // and bezier segments. Create 2d, 3d and BrepEdge elements for each segment.
164  // Will need to use the bboxes of each element to
165  // build the overall bounding box for the face. Use bGrowBox to expand
166  // a single box.
167  struct line_seg *lsg;
168  struct carc_seg *csg;
169  struct bezier_seg *bsg;
170  uint32_t *lng;
171  for (size_t i = 0; i < (&eip->curve)->count; i++) {
172  lng = (uint32_t *)(&eip->curve)->segment[i];
173  switch (*lng) {
174  case CURVE_LSEG_MAGIC:
175  {
176  lsg = (struct line_seg *)lng;
177  ON_Curve* lsg3d = new ON_LineCurve((*b)->m_V[lsg->start].Point(), (*b)->m_V[lsg->end].Point());
178  lsg3d->SetDomain(0.0, 1.0);
179  (*b)->m_C3.Append(lsg3d);
180  }
181  break;
182  case CURVE_CARC_MAGIC:
183  csg = (struct carc_seg *)lng;
184  if (csg->radius < 0) {
185  ON_3dPoint cntrpt = (*b)->m_V[csg->end].Point();
186  ON_3dPoint edgept = (*b)->m_V[csg->start].Point();
187  ON_Plane cplane = ON_Plane(cntrpt, plane_x_dir, plane_y_dir);
188  ON_Circle c3dcirc = ON_Circle(cplane, cntrpt.DistanceTo(edgept));
189  ON_Curve* c3d = new ON_ArcCurve((const ON_Circle)c3dcirc);
190  c3d->SetDomain(0.0, 1.0);
191  (*b)->m_C3.Append(c3d);
192  } else {
193  // need to calculated 3rd point on arc - look to sketch.c around line 581 for
194  // logic
195  }
196  break;
197  case CURVE_BEZIER_MAGIC:
198  bsg = (struct bezier_seg *)lng;
199  {
200  ON_3dPointArray bezpoints(bsg->degree + 1);
201  for (int j = 0; j < bsg->degree + 1; j++) {
202  bezpoints.Append((*b)->m_V[bsg->ctl_points[j]].Point());
203  }
204  ON_BezierCurve bez3d = ON_BezierCurve((const ON_3dPointArray)bezpoints);
205  ON_NurbsCurve* beznurb3d = ON_NurbsCurve::New();
206  bez3d.GetNurbForm(*beznurb3d);
207  beznurb3d->SetDomain(0.0, 1.0);
208  (*b)->m_C3.Append(beznurb3d);
209  }
210  break;
211  default:
212  bu_log("Unhandled sketch object\n");
213  break;
214  }
215  }
216 
217  // Create the plane surface and brep face.
218  ON_PlaneSurface *sketch_surf = new ON_PlaneSurface(sketch_plane);
219  (*b)->m_S.Append(sketch_surf);
220  int surfindex = (*b)->m_S.Count();
221  ON_BrepFace& face = (*b)->NewFace(surfindex - 1);
222 
223  // For the purposes of BREP creation, it is necessary to identify
224  // loops created by sketch segments. This information is not stored
225  // in the sketch data structures themselves, and thus must be deduced
226  FindLoops(b);
227  const ON_BrepLoop* tloop = (*b)->m_L.First();
228  sketch_surf->SetDomain(0, tloop->m_pbox.m_min.x, tloop->m_pbox.m_max.x);
229  sketch_surf->SetDomain(1, tloop->m_pbox.m_min.y, tloop->m_pbox.m_max.y);
230  sketch_surf->SetExtents(0, sketch_surf->Domain(0));
231  sketch_surf->SetExtents(1, sketch_surf->Domain(1));
232  (*b)->SetTrimIsoFlags(face);
233  (*b)->FlipFace(face);
234  (*b)->Compact();
235 }
236 
237 
238 // Local Variables:
239 // tab-width: 8
240 // mode: C++
241 // c-basic-offset: 4
242 // indent-tabs-mode: t
243 // c-file-style: "stroustrup"
244 // End:
245 // ex: shiftwidth=4 tabstop=8
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define VSET(a, b, c, d)
Definition: color.c:53
#define CURVE_CARC_MAGIC
Definition: magic.h:198
void FindLoops(ON_Brep **b)
Definition: sketch_brep.cpp:32
Header file for the BRL-CAD common definitions.
#define CURVE_BEZIER_MAGIC
Definition: magic.h:197
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
#define UNUSED(parameter)
Definition: common.h:239
Support for uniform tolerances.
Definition: tol.h:71
void rt_sketch_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
void * idb_ptr
Definition: raytrace.h:195
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define CURVE_LSEG_MAGIC
Definition: magic.h:199