1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 #include "opennurbs.h"
17
18
19 static
FindLinearEdge(const ON_Brep & brep,int vi0,int vi1)20 const ON_BrepEdge* FindLinearEdge( const ON_Brep& brep, int vi0, int vi1 )
21 {
22 // searchs for a linear edge connecting the vertices
23 // brep.m_V[vi0] and brep.m_V[vi1].
24 if ( vi0 < 0 || vi0 >= brep.m_V.Count() )
25 return NULL;
26 if ( vi1 < 0 || vi1 >= brep.m_V.Count() )
27 return NULL;
28 if ( vi0 == vi1 )
29 return NULL;
30 const ON_BrepVertex& v0 = brep.m_V[vi0];
31 //const ON_BrepVertex& v1 = brep.m_V[vi1];
32 int vei;
33 for ( vei = 0; vei < v0.m_ei.Count(); vei++ )
34 {
35 const ON_BrepEdge* edge = brep.Edge( v0.m_ei[vei] );
36 if ( !edge )
37 continue;
38 if ( edge->m_vi[0] != vi0 && edge->m_vi[1] != vi0 )
39 continue;
40 if ( edge->m_vi[0] != vi1 && edge->m_vi[1] != vi1 )
41 continue;
42 if ( !edge->IsLinear() )
43 continue;
44 return edge;
45 }
46 return NULL;
47 }
48
49 static
SynchFaceOrientation(ON_Brep & brep,int fi)50 void SynchFaceOrientation( ON_Brep& brep, int fi )
51 {
52 const ON_BrepFace* face = brep.Face(fi);
53 if ( face )
54 {
55 int flip = -1, fli, lti;
56 for ( fli = 0; fli < face->m_li.Count(); fli++ )
57 {
58 const ON_BrepLoop* loop = brep.Loop( face->m_li[fli] );
59 if ( !loop )
60 continue;
61 for ( lti = 0; lti < loop->m_ti.Count(); lti++ )
62 {
63 const ON_BrepTrim* trim = brep.Trim( loop->m_ti[lti] );
64 if ( !trim )
65 continue;
66 const ON_BrepEdge* edge = brep.Edge( trim->m_ei );
67 if ( !edge )
68 continue;
69 if ( edge->m_ti.Count() != 2 )
70 continue;
71 const ON_BrepTrim* trim0 = brep.Trim( edge->m_ti[0] );
72 const ON_BrepTrim* trim1 = brep.Trim( edge->m_ti[1] );
73 if ( !trim0 || !trim1 )
74 continue;
75 bool bRev0 = trim0->m_bRev3d ? true : false;
76 bool bRev1 = trim1->m_bRev3d ? true : false;
77 if ( bRev0 == bRev1 )
78 {
79 if ( flip == -1 )
80 flip = 1;
81 else if (flip != 1 )
82 return;
83 }
84 else
85 {
86 if ( flip == -1 )
87 flip = 0;
88 else if (flip != 0 )
89 return;
90 }
91 }
92 }
93 if ( flip == 1 )
94 brep.FlipFace(brep.m_F[fi]);
95 }
96 }
97
NewRuledFace(const ON_BrepEdge & edgeA,bool bRevEdgeA,const ON_BrepEdge & edgeB,bool bRevEdgeB)98 ON_BrepFace* ON_Brep::NewRuledFace(
99 const ON_BrepEdge& edgeA,
100 bool bRevEdgeA,
101 const ON_BrepEdge& edgeB,
102 bool bRevEdgeB
103 )
104 {
105 if ( edgeA.m_edge_index == edgeB.m_edge_index )
106 return NULL;
107 if ( Edge( edgeA.m_edge_index) != &edgeA )
108 return NULL;
109 if ( Edge( edgeB.m_edge_index) != &edgeB )
110 return NULL;
111
112 ON_NurbsCurve cA, cB;
113 if ( !edgeA.GetNurbForm( cA ) )
114 return NULL;
115 if ( bRevEdgeA )
116 cA.Reverse();
117 if ( !edgeB.GetNurbForm( cB ) )
118 return NULL;
119 if ( bRevEdgeB )
120 cB.Reverse();
121 ON_NurbsSurface* srf = ON_NurbsSurface::New();
122 if ( !srf->CreateRuledSurface( cA, cB ) )
123 {
124 delete srf;
125 return NULL;
126 }
127
128 // corner vertices (sw,se,ne,nw)
129 int vid[4] = {-1,-1,-1,-1};
130 vid[0] = edgeA.m_vi[bRevEdgeA?1:0];
131 vid[1] = edgeA.m_vi[bRevEdgeA?0:1];
132 vid[2] = edgeB.m_vi[bRevEdgeB?0:1];
133 vid[3] = edgeB.m_vi[bRevEdgeB?1:0];
134
135 if ( vid[1] == vid[2] )
136 {
137 // make sure surface has a singular east side
138 srf->CollapseSide( 1 );
139 }
140
141 if ( vid[1] == vid[2] )
142 {
143 // make sure surface has a singular west side
144 srf->CollapseSide( 3 );
145 }
146
147 // side edges (s,e,n,w)
148 int eid[4] = {-1,-1,-1,-1};
149 ON_BOOL32 bRev3d[4] = {false,false,false,false};
150
151 // south side
152 eid[0] = edgeA.m_edge_index;
153 bRev3d[0] = bRevEdgeA;
154
155 // east side
156 const ON_BrepEdge* east_edge = FindLinearEdge( *this, vid[1], vid[2] );
157 if ( east_edge )
158 {
159 eid[1] = east_edge->m_edge_index;
160 bRev3d[1] = (east_edge->m_vi[0] == vid[2]);
161 }
162
163 // north side
164 eid[2] = edgeB.m_edge_index;
165 bRev3d[2] = !bRevEdgeB;
166
167 // west side
168 const ON_BrepEdge* west_edge = FindLinearEdge( *this, vid[3], vid[0] );
169 if ( west_edge )
170 {
171 eid[3] = west_edge->m_edge_index;
172 bRev3d[3] = (west_edge->m_vi[0] == vid[0]);
173 }
174
175 ON_BrepFace* face = NewFace( srf, vid, eid, bRev3d );
176 if ( face )
177 SynchFaceOrientation( *this, face->m_face_index );
178 return face;
179 }
180
181
NewConeFace(const ON_BrepVertex & vertex,const ON_BrepEdge & edge,bool bRevEdge)182 ON_BrepFace* ON_Brep::NewConeFace(
183 const ON_BrepVertex& vertex,
184 const ON_BrepEdge& edge,
185 bool bRevEdge
186 )
187 {
188 if ( Edge( edge.m_edge_index) != &edge )
189 return NULL;
190 if ( Vertex( vertex.m_vertex_index) != &vertex )
191 return NULL;
192 if ( edge.m_vi[0] == vertex.m_vertex_index )
193 return NULL;
194 if ( edge.m_vi[1] == vertex.m_vertex_index )
195 return NULL;
196 ON_NurbsCurve c;
197 if ( !edge.GetNurbForm( c ) )
198 return NULL;
199 if ( bRevEdge )
200 c.Reverse();
201 ON_NurbsSurface* srf = ON_NurbsSurface::New();
202 if ( !srf->CreateConeSurface( vertex.point, c ) )
203 {
204 delete srf;
205 return NULL;
206 }
207
208 // corner vertices (sw,se,ne,nw)
209 int vid[4] = {-1,-1,-1,-1};
210 vid[0] = edge.m_vi[bRevEdge?1:0];
211 vid[1] = edge.m_vi[bRevEdge?0:1];
212 vid[2] = vertex.m_vertex_index;
213 vid[3] = vertex.m_vertex_index;
214
215 // side edges (s,e,n,w)
216 int eid[4] = {-1,-1,-1,-1};
217 ON_BOOL32 bRev3d[4] = {false,false,false,false};
218
219 // south side
220 eid[0] = edge.m_edge_index;
221 bRev3d[0] = bRevEdge;
222
223 // east side
224 const ON_BrepEdge* east_edge = FindLinearEdge( *this, vid[1], vid[2] );
225 if ( east_edge )
226 {
227 eid[1] = east_edge->m_edge_index;
228 bRev3d[1] = (east_edge->m_vi[0] == vid[2]);
229 }
230
231 // west side
232 const ON_BrepEdge* west_edge = FindLinearEdge( *this, vid[3], vid[0] );
233 if ( west_edge )
234 {
235 eid[3] = west_edge->m_edge_index;
236 bRev3d[3] = (west_edge->m_vi[0] == vid[0]);
237 }
238
239 ON_BrepFace* face = NewFace( srf, vid, eid, bRev3d );
240 if ( face )
241 SynchFaceOrientation( *this, face->m_face_index );
242 return face;
243 }
244
245
SetMesh(ON::mesh_type mt,ON_Mesh * mesh)246 bool ON_BrepFace::SetMesh( ON::mesh_type mt, ON_Mesh* mesh )
247 {
248 // TODO move next to ON_BrepFace::Mesh() when opennurbs_brep.cpp is available
249 bool rc = true;
250 switch ( mt )
251 {
252 case ON::render_mesh:
253 if ( m_render_mesh )
254 delete m_render_mesh;
255 m_render_mesh = mesh;
256 break;
257
258 case ON::analysis_mesh:
259 if ( m_analysis_mesh )
260 delete m_analysis_mesh;
261 m_analysis_mesh = mesh;
262 break;
263
264 case ON::preview_mesh:
265 if ( m_preview_mesh )
266 delete m_preview_mesh;
267 m_preview_mesh = mesh;
268 break;
269
270 default:
271 rc = false;
272 }
273
274 return rc;
275 }
276
277
SetTrimBoundingBoxes(ON_BOOL32 bLazy)278 bool ON_Brep::SetTrimBoundingBoxes( ON_BOOL32 bLazy )
279 {
280 bool rc = true;
281 int fi, face_count = m_F.Count();
282 for ( fi = 0; fi < face_count; fi++ )
283 {
284 if ( !SetTrimBoundingBoxes( m_F[fi], bLazy ) )
285 rc = false;
286 }
287 return rc;
288 }
289
SetTrimBoundingBoxes(ON_BrepFace & face,ON_BOOL32 bLazy)290 bool ON_Brep::SetTrimBoundingBoxes( ON_BrepFace& face, ON_BOOL32 bLazy )
291 {
292 bool rc = true;
293 int li, fli, loop_count = m_L.Count(), fl_count = face.m_li.Count();;
294 for ( fli = 0; fli < fl_count; fli++ )
295 {
296 li = face.m_li[fli];
297 if ( li >= 0 && li < loop_count )
298 {
299 if ( !SetTrimBoundingBoxes( m_L[li], bLazy ) )
300 rc = false;
301 }
302 }
303 return rc;
304 }
305
SetTrimBoundingBoxes(ON_BrepLoop & loop,ON_BOOL32 bLazy)306 bool ON_Brep::SetTrimBoundingBoxes( ON_BrepLoop& loop, ON_BOOL32 bLazy )
307 {
308 // TL_Brep overrides this function and computes much tighter
309 // bounding boxes that take trim.m_t[] into account.
310 ON_BOOL32 rc = true;
311 int ti, lti, trim_count = m_T.Count(), lt_count = loop.m_ti.Count();
312 ON_BOOL32 bSetLoopBox = true;
313 if ( bLazy && loop.m_pbox.IsValid() )
314 bSetLoopBox = false;
315 else
316 loop.m_pbox.Destroy();
317 for ( lti = 0; lti < lt_count; lti++ )
318 {
319 ti = loop.m_ti[lti];
320 if ( ti >= 0 && ti < trim_count )
321 {
322 if ( !SetTrimBoundingBox( m_T[ti], bLazy ) )
323 rc = false;
324 else if ( bSetLoopBox )
325 loop.m_pbox.Union( m_T[ti].m_pbox );
326 }
327 }
328 return (rc && loop.m_pbox.IsValid()) ? true : false;
329 }
330
SetTrimBoundingBox(ON_BrepTrim & trim,ON_BOOL32 bLazy)331 bool ON_Brep::SetTrimBoundingBox( ON_BrepTrim& trim, ON_BOOL32 bLazy )
332 {
333 // TL_Brep overrides this function and computes much
334 // tighter bounding boxes that take trim.m_t[] into account.
335 ON_BOOL32 rc = true;
336 if ( !trim.m_pbox.IsValid() || !bLazy )
337 {
338 trim.m_pbox.Destroy();
339 if ( trim.ProxyCurve() )
340 {
341 trim.m_pbox = trim.BoundingBox();
342 trim.m_pbox.m_min.z = 0.0;
343 trim.m_pbox.m_max.z = 0.0;
344 }
345 }
346 return (rc && trim.m_pbox.IsValid()) ? true : false;
347 }
348
SetTolerancesBoxesAndFlags(ON_BOOL32 bLazy,ON_BOOL32 bSetVertexTolerances,ON_BOOL32 bSetEdgeTolerances,ON_BOOL32 bSetTrimTolerances,ON_BOOL32 bSetTrimIsoFlags,ON_BOOL32 bSetTrimTypeFlags,ON_BOOL32 bSetLoopTypeFlags,ON_BOOL32 bSetTrimBoxes)349 void ON_Brep::SetTolerancesBoxesAndFlags(
350 ON_BOOL32 bLazy,
351 ON_BOOL32 bSetVertexTolerances,
352 ON_BOOL32 bSetEdgeTolerances,
353 ON_BOOL32 bSetTrimTolerances,
354 ON_BOOL32 bSetTrimIsoFlags,
355 ON_BOOL32 bSetTrimTypeFlags,
356 ON_BOOL32 bSetLoopTypeFlags,
357 ON_BOOL32 bSetTrimBoxes
358 )
359 {
360 int ei, ti, li;
361 const int trim_count = m_T.Count();
362 const int loop_count = m_L.Count();
363 const int edge_count = m_E.Count();
364 if ( bSetVertexTolerances )
365 SetVertexTolerances(bLazy);
366 if ( bSetEdgeTolerances )
367 {
368 for ( ei = 0; ei < edge_count; ei++ )
369 SetEdgeTolerance(m_E[ei],bLazy);
370 }
371 if ( bSetTrimTolerances )
372 {
373 for ( ti = 0; ti < trim_count; ti++ )
374 SetTrimTolerance(m_T[ti],bLazy);
375 }
376 if ( bSetTrimIsoFlags )
377 SetTrimIsoFlags();
378 if ( bSetTrimTypeFlags )
379 SetTrimTypeFlags(bLazy);
380 if ( bSetTrimTypeFlags )
381 SetTrimTypeFlags(bLazy);
382 if ( bSetLoopTypeFlags )
383 {
384 for ( li = 0; li < loop_count; li++ )
385 {
386 ON_BrepLoop& loop = m_L[li];
387 if ( loop.m_type == ON_BrepLoop::unknown || !bLazy )
388 {
389 loop.m_type = ComputeLoopType( loop );
390 }
391 }
392 }
393 if ( bSetTrimBoxes )
394 SetTrimBoundingBoxes(bLazy);
395 }
396
397 static
CheckForMatchingVertexIndices(int i,int j,int corner_vi[4])398 bool CheckForMatchingVertexIndices( int i, int j, int corner_vi[4] )
399 {
400 ON_BOOL32 rc = false;
401 if ( corner_vi[i] >= 0 || corner_vi[j] >= 0 )
402 {
403 if ( corner_vi[i] == -1 )
404 {
405 corner_vi[i] = corner_vi[j];
406 rc = true;
407 }
408 else if ( corner_vi[j] == -1 )
409 {
410 corner_vi[j] = corner_vi[i];
411 rc = true;
412 }
413 else if ( corner_vi[i] == corner_vi[j] )
414 {
415 rc = true;
416 }
417 }
418 (void)rc;//G+Smo
419 return true;
420 }
421
422
NewFace(ON_Surface * pSurface,int vid[4],int eid[4],ON_BOOL32 bRev3d[4])423 ON_BrepFace* ON_Brep::NewFace(
424 ON_Surface* pSurface,
425 int vid[4],
426 int eid[4],
427 ON_BOOL32 bRev3d[4]
428 )
429 {
430 m_bbox.Destroy();
431 m_is_solid = 0;
432 ON_BOOL32 bAddedSurface = false;
433 ON_BrepFace* pFace = NULL;
434 if ( !pSurface )
435 return NULL;
436 int si;
437 for ( si = 0; si < m_S.Count(); si++ )
438 {
439 if ( pSurface == m_S[si] )
440 break;
441 }
442 if ( si >= m_S.Count() )
443 {
444 si = AddSurface(pSurface);
445 bAddedSurface = (si >= 0);
446 }
447 int face_index = NewFace(si).m_face_index;
448 if ( NewOuterLoop( face_index, vid, eid, bRev3d ) )
449 {
450 pFace = &m_F[face_index];
451 }
452 else
453 {
454 // failed
455 if ( bAddedSurface )
456 {
457 m_S[si] = 0;
458 if ( m_S.Count() == si+1 )
459 m_S.SetCount(si);
460 }
461 DeleteFace( m_F[face_index], false );
462 if ( m_F.Count() == face_index+1 )
463 {
464 m_F.SetCount(face_index);
465 }
466 }
467 return pFace;
468 }
469
470
NewOuterLoop(int face_index,int vid[4],int eid[4],ON_BOOL32 bRev3d[4])471 ON_BrepLoop* ON_Brep::NewOuterLoop(
472 int face_index,
473 int vid[4],
474 int eid[4],
475 ON_BOOL32 bRev3d[4]
476 )
477 {
478 m_is_solid = 0;
479 if ( face_index < 0 || face_index >= m_F.Count() )
480 return NULL;
481 ON_BrepFace& face = m_F[face_index];
482 const ON_Surface* pSurface = face.SurfaceOf();
483 if (!pSurface)
484 return NULL;
485
486 double u[2], v[2];
487 if (!pSurface->GetDomain(0, &u[0], &u[1]))
488 return 0;
489 if (!pSurface->GetDomain(1, &v[0], &v[1]))
490 return 0;
491
492 ON_3dPoint srf_P[2][2];
493 if ( !pSurface->EvPoint(u[0],v[0],srf_P[0][0] ) )
494 return 0;
495 if ( !pSurface->EvPoint(u[1],v[0],srf_P[1][0] ) )
496 return 0;
497 if ( !pSurface->EvPoint(u[0],v[1],srf_P[0][1] ) )
498 return 0;
499 if ( !pSurface->EvPoint(u[1],v[1],srf_P[1][1] ) )
500 return 0;
501
502
503 ON_BOOL32 bIsSingular[4]; // south, east, north, west
504 ON_BOOL32 bIsClosed[2]; // u direction, v direction
505 int i, eti;
506 ON_Curve* c3[4] = {NULL,NULL,NULL,NULL};
507
508 for ( i = 0; i < 4; i++ )
509 {
510 if ( bRev3d[i] )
511 bRev3d[i] = 1; // do this so we can use 1-bRev3d[i] as an array index
512 }
513
514 // check specified edge indices
515 for ( i = 0; i < 4; i++ )
516 {
517 if ( eid[i] != -1 )
518 {
519 if ( eid[i] < 0 || eid[i] >= m_E.Count() )
520 {
521 ON_ERROR("Bad edge index passed to ON_BrepNewFace.");
522 return 0;
523 }
524 const int* edge_vi = m_E[eid[i]].m_vi;
525 int vi0 = edge_vi[bRev3d[i]];
526 int vi1 = edge_vi[1-bRev3d[i]];
527 if ( vi0 < 0 || vi1 < 0 )
528 {
529 ON_ERROR("ON_Brep::NewFace(ON_Surface*,...) error: Bad edge vertex informtion.");
530 return 0;
531 }
532 if ( vid[i] == -1 )
533 vid[i] = vi0;
534 else if ( vid[i] != vi0 )
535 {
536 ON_ERROR("ON_Brep::NewFace(ON_Surface*,...) error: Edge and vertex informtion do not match.");
537 return 0;
538 }
539 if ( vid[(i+1)%4] == -1 )
540 vid[(i+1)%4] = vi1;
541 else if ( vid[(i+1)%4] != vi1 )
542 {
543 ON_ERROR("ON_Brep::NewFace(ON_Surface*,...) error: Edge and vertex informtion do not match.");
544 return 0;
545 }
546 }
547 }
548
549 // check specified vertex indices
550 for ( i = 0; i < 4; i++ )
551 {
552 if ( vid[i] != -1 )
553 {
554 if ( vid[i] < 0 || vid[i] >= m_V.Count() )
555 {
556 ON_ERROR("Bad vertex index passed to ON_Brep::NewFace.");
557 return 0;
558 }
559 }
560 }
561
562 for ( i = 0; i < 4; i++ )
563 bIsSingular[i] = pSurface->IsSingular(i);
564 for ( i = 0; i < 2; i++ )
565 bIsClosed[i] = pSurface->IsClosed(i);
566
567 for (i = 0; i < 2; i++ )
568 {
569 if ( bIsClosed[i] )
570 {
571 int j = i?0:1;
572 int k = j+2;
573 if ( eid[j] == -1 && eid[k] != -1)
574 {
575 eid[j] = eid[k];
576 bRev3d[j] = 1-bRev3d[k];
577 }
578 else if ( eid[k] == -1 && eid[j] != -1)
579 {
580 eid[k] = eid[j];
581 bRev3d[k] = 1-bRev3d[j];
582 }
583 else if ( eid[k] != -1 || eid[j] != -1)
584 {
585 if ( eid[j] != eid[k] || bRev3d[j] != 1-bRev3d[k] )
586 {
587 ON_ERROR("Bad edge information passed to ON_Brep::NewFace.");
588 return 0;
589 }
590 }
591 }
592 }
593
594 // if surface has singularities or is closed, make sure vertex and edge information is correct
595 for ( i = 0; i < 4; i++ )
596 {
597 if ( bIsSingular[i] )
598 {
599 if ( eid[i] != -1 || bRev3d[i] )
600 {
601 ON_ERROR("Bad edge information passed to ON_Brep::NewFace.");
602 return 0;
603 }
604 }
605 if ( bIsSingular[i] || bIsClosed[i%2] )
606 {
607 if ( !CheckForMatchingVertexIndices(i,(i+1)%4,vid) )
608 {
609 ON_ERROR("Bad vertex indices passed to ON_Brep::NewFace.");
610 return 0;
611 }
612 }
613 }
614
615 m_C3.Reserve( m_C3.Count() + 4 );
616 // create missing 3d curves
617 bool bEdgeIsClosed[4]; // true if 3d edge is closed or edge is singular.
618 for ( i = 0; i < 4; i++ )
619 {
620 bEdgeIsClosed[i] = false;
621 if ( eid[i] != -1 )
622 {
623 const ON_BrepEdge& edge = m_E[eid[i]];
624 bEdgeIsClosed[i] = (edge.m_vi[0] == edge.m_vi[1]);
625 continue;
626 }
627 if ( bIsSingular[i] )
628 {
629 bEdgeIsClosed[i] = true;
630 continue;
631 }
632 if ( i >= 2 && bIsClosed[(i==2)?1:0] )
633 {
634 bEdgeIsClosed[i] = bEdgeIsClosed[i-2];
635 continue;
636 }
637 switch(i)
638 {
639 case 0: // south side
640 c3[i] = pSurface->IsoCurve(i%2, v[0]);
641 break;
642 case 1: // east side
643 c3[i] = pSurface->IsoCurve(i%2, u[1]);
644 break;
645 case 2: // north side
646 c3[i] = pSurface->IsoCurve(i%2, v[1]);
647 break;
648 case 3: // west side
649 c3[i] = pSurface->IsoCurve(i%2, u[0]);
650 break;
651 }
652 if ( !c3[i] )
653 {
654 ON_ERROR("ON_Brep::NewLoop unable to make 3d edge curve.");
655 return 0;
656 }
657 if ( pSurface->IsClosed(i%2) )
658 bEdgeIsClosed[i] = true;
659 else
660 bEdgeIsClosed[i] = c3[i]->IsClosed()?true:false;
661 if ( (i <= 1 && bRev3d[i]) || (i >= 2 && !bRev3d[i]) )
662 {
663 c3[i]->Reverse();
664 }
665 }
666
667 if ( m_V.Capacity() < 2 )
668 m_V.Reserve(4);
669
670 // create missing vertices
671 if ( vid[0] == -1 )
672 {
673 if ( vid[1] >= 0 && bEdgeIsClosed[0] )
674 vid[0] = vid[1];
675 else if ( vid[3] >= 0 && bEdgeIsClosed[3] )
676 vid[0] = vid[3];
677 else
678 vid[0] = NewVertex( srf_P[0][0],0.0).m_vertex_index;
679 }
680
681 if ( vid[1] == -1 )
682 {
683 if ( bEdgeIsClosed[0] )
684 vid[1] = vid[0];
685 else if ( vid[2] >= 0 && bEdgeIsClosed[1] )
686 vid[1] = vid[2];
687 else
688 vid[1] = NewVertex(srf_P[1][0],0.0).m_vertex_index;
689 }
690
691 if ( vid[2] == -1 )
692 {
693 if ( bEdgeIsClosed[1] )
694 vid[2] = vid[1];
695 else if (vid[3] >= 0 && bEdgeIsClosed[2] )
696 vid[2] = vid[3];
697 else
698 vid[2] = NewVertex( srf_P[1][1],0.0).m_vertex_index;
699 }
700
701 if ( vid[3] == -1 )
702 {
703 if ( bEdgeIsClosed[2] )
704 vid[3] = vid[2];
705 else if ( bEdgeIsClosed[3] )
706 vid[3] = vid[0];
707 else
708 vid[3] = NewVertex( srf_P[0][1],0.0).m_vertex_index;
709 }
710
711 if ( m_E.Capacity() < 4 )
712 m_E.Reserve(4);
713
714 // create missing edges
715 for ( i = 0; i < 4; i++ )
716 {
717 if ( c3[i] )
718 {
719 int i0, i1;
720 if ( bRev3d[i] )
721 {
722 i0 = (i+1)%4;
723 i1 = i;
724 }
725 else
726 {
727 i0 = i;
728 i1 = (i+1)%4;
729 }
730 ON_BrepEdge& edge = NewEdge( m_V[vid[i0]], m_V[vid[i1]], AddEdgeCurve( c3[i] ) );
731 edge.m_tolerance = 0.0;
732 eid[i] = edge.m_edge_index;
733 if ( i == 0 && bIsClosed[1] )
734 {
735 eid[2] = eid[0];
736 bRev3d[2] = 1-bRev3d[0];
737 }
738 else if ( i == 1 && bIsClosed[0] )
739 {
740 eid[3] = eid[1];
741 bRev3d[3] = 1-bRev3d[1];
742 }
743 }
744 }
745
746 m_T.Reserve( m_T.Count() + 4 );
747 m_C2.Reserve( m_C2.Count() + 4 );
748
749 ON_BrepLoop& loop = NewLoop( ON_BrepLoop::outer, face );
750
751 loop.m_pbox.m_min.x = u[0];
752 loop.m_pbox.m_min.y = v[0];
753 loop.m_pbox.m_min.z = 0.0;
754
755 loop.m_pbox.m_max.x = u[1];
756 loop.m_pbox.m_max.y = v[1];
757 loop.m_pbox.m_max.z = 0.0;
758
759 ON_3dPoint corners[4];
760 corners[0].Set(u[0],v[0],0.0);
761 corners[1].Set(u[1],v[0],0.0);
762 corners[2].Set(u[1],v[1],0.0);
763 corners[3].Set(u[0],v[1],0.0);
764
765 ON_Surface::ISO srf_iso[4] = {ON_Surface::S_iso,ON_Surface::E_iso,ON_Surface::N_iso,ON_Surface::W_iso};
766
767 for ( i = 0; i < 4; i++ )
768 {
769 ON_NurbsCurve* c2 = new ON_NurbsCurve( 2, 0, 2, 2 );
770 c2->SetCV(0,corners[i]);
771 c2->SetCV(1,corners[(i+1)%4]);
772 c2->m_knot[0] = 0.0;
773 c2->m_knot[1] = 1.0;
774 if ( i%2 )
775 c2->SetDomain(v[0],v[1]);
776 else
777 c2->SetDomain(u[0],u[1]);
778 int c2i = AddTrimCurve( c2 );
779 if ( bIsSingular[i] )
780 NewSingularTrim( m_V[vid[i]],loop,srf_iso[i],c2i);
781 else
782 {
783 ON_BrepTrim& trim = NewTrim( m_E[eid[i]], bRev3d[i], loop, c2i);
784 trim.m_iso = srf_iso[i];
785 if ( bIsClosed[(i+1)%2] )
786 trim.m_type = ON_BrepTrim::seam;
787 else {
788 trim.m_type = ON_BrepTrim::boundary;
789 const ON_BrepEdge& edge = m_E[eid[i]];
790 if ( edge.m_ti.Count() > 1 )
791 {
792 for ( eti = 0; eti < edge.m_ti.Count(); eti++ )
793 {
794 m_T[edge.m_ti[eti]].m_type = ON_BrepTrim::mated;
795 }
796 }
797 }
798 trim.m_tolerance[0] = 0.0;
799 trim.m_tolerance[1] = 0.0;
800 trim.m__legacy_2d_tol = 0.0;
801 trim.m__legacy_3d_tol = 0.0;
802 trim.m__legacy_flags_Set(-1,1);
803 }
804 }
805
806 return &m_L[loop.m_loop_index];
807 }
808
809
810
811
ON_BrepBox(const ON_3dPoint * box_corners,ON_Brep * pBrep)812 ON_Brep* ON_BrepBox( const ON_3dPoint* box_corners, ON_Brep* pBrep )
813 {
814 ON_Brep* brep = 0;
815 int vi, ei, fi, si, c2i;
816 if (box_corners)
817 {
818 if ( pBrep ) {
819 pBrep->Destroy();
820 brep = pBrep;
821 }
822 else
823 brep = new ON_Brep();
824 brep->m_C2.Reserve(24);
825 brep->m_C3.Reserve(12);
826 brep->m_S.Reserve(6);
827 brep->m_V.Reserve(8);
828 brep->m_E.Reserve(12);
829 brep->m_L.Reserve(6);
830 brep->m_T.Reserve(24);
831 brep->m_F.Reserve(6);
832 for ( vi = 0; vi < 8; vi++ )
833 {
834 brep->NewVertex( box_corners[vi], 0.0 );
835 }
836 for ( ei = 0; ei < 4; ei++ )
837 {
838 ON_BrepVertex& v0 = brep->m_V[ei];
839 ON_BrepVertex& v1 = brep->m_V[(ei+1)%4];
840 brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
841 brep->NewEdge( v0, v1, ei, NULL, 0.0 );
842 }
843 for ( ei = 4; ei < 8; ei++ )
844 {
845 ON_BrepVertex& v0 = brep->m_V[ei];
846 ON_BrepVertex& v1 = brep->m_V[ei==7?4:(ei+1)];
847 brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
848 brep->NewEdge( v0, v1, ei, NULL, 0.0 );
849 }
850 for ( ei = 8; ei < 12; ei++ )
851 {
852 ON_BrepVertex& v0 = brep->m_V[ei-8];
853 ON_BrepVertex& v1 = brep->m_V[ei-4];
854 brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
855 brep->NewEdge( v0, v1, ei, NULL, 0.0 );
856 }
857
858 /*
859 // v7_______e6_____v6
860 // |\ |\
861 // | e7 | e5
862 // | \ ______e4_____\
863 // e11 v4 | v5
864 // | | e10 |
865 // | | | |
866 // 3---|---e2-----2 e9
867 // \ e8 \ |
868 // e3 | e1 |
869 // \ | \ |
870 // \v0_____e0_____\v1
871 */
872
873 struct {
874 int e[4], bRev[4];
875 } f[6] = {
876 {{0, 9, 4, 8}, {false, false, true, true}},
877 {{1,10, 5, 9}, {false, false, true, true}},
878 {{2,11, 6,10}, {false, false, true, true}},
879 {{3, 8, 7,11}, {false, false, true, true}},
880 {{3, 2, 1, 0}, {true, true, true, true}},
881 {{4, 5, 6, 7}, {false, false, false, false}}
882 };
883 for ( fi = 0; fi < 6; fi++ )
884 {
885 ON_BrepEdge& e0 = brep->m_E[f[fi].e[0]];
886 ON_BrepEdge& e1 = brep->m_E[f[fi].e[1]];
887 ON_BrepEdge& e2 = brep->m_E[f[fi].e[2]];
888 ON_BrepEdge& e3 = brep->m_E[f[fi].e[3]];
889 ON_BrepVertex& v0 = brep->m_V[e0.m_vi[f[fi].bRev[0]?1:0]];
890 ON_BrepVertex& v1 = brep->m_V[e1.m_vi[f[fi].bRev[1]?1:0]];
891 ON_BrepVertex& v2 = brep->m_V[e2.m_vi[f[fi].bRev[2]?1:0]];
892 ON_BrepVertex& v3 = brep->m_V[e3.m_vi[f[fi].bRev[3]?1:0]];
893
894 si = brep->AddSurface( ON_NurbsSurfaceQuadrilateral( v0.point, v1.point, v2.point, v3.point ) );
895 ON_Interval s = brep->m_S[si]->Domain(0);
896 ON_Interval t = brep->m_S[si]->Domain(1);
897 ON_2dPoint p0(s[0],t[0]);
898 ON_2dPoint p1(s[1],t[0]);
899 ON_2dPoint p2(s[1],t[1]);
900 ON_2dPoint p3(s[0],t[1]);
901
902 ON_BrepFace& face = brep->NewFace( si );
903 ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, face );
904
905 loop.m_pbox.m_min.x = s[0];
906 loop.m_pbox.m_min.y = t[0];
907 loop.m_pbox.m_min.z = 0.0;
908
909 loop.m_pbox.m_max.x = s[1];
910 loop.m_pbox.m_max.y = t[1];
911 loop.m_pbox.m_max.z = 0.0;
912
913 // south side of surface
914 c2i = brep->AddTrimCurve( new ON_LineCurve( p0, p1 ) );
915 ON_BrepTrim& trim0 = brep->NewTrim( e0, f[fi].bRev[0], loop, c2i );
916 trim0.m_tolerance[0] = 0.0;
917 trim0.m_tolerance[1] = 0.0;
918 trim0.m_type = (trim0.m_vi[0] != trim0.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
919 trim0.m_iso = ON_Surface::S_iso;
920
921 // east side of surface
922 c2i = brep->AddTrimCurve( new ON_LineCurve( p1, p2 ) );
923 ON_BrepTrim& trim1 = brep->NewTrim( e1, f[fi].bRev[1], loop, c2i );
924 trim1.m_tolerance[0] = 0.0;
925 trim1.m_tolerance[1] = 0.0;
926 trim1.m_type = (trim1.m_vi[0] != trim1.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
927 trim1.m_iso = ON_Surface::E_iso;
928
929 // north side of surface
930 c2i = brep->AddTrimCurve( new ON_LineCurve( p2, p3 ) );
931 ON_BrepTrim& trim2 = brep->NewTrim( e2, f[fi].bRev[2], loop, c2i );
932 trim2.m_tolerance[0] = 0.0;
933 trim2.m_tolerance[1] = 0.0;
934 trim2.m_type = (trim2.m_vi[0] != trim2.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
935 trim2.m_iso = ON_Surface::N_iso;
936
937 // west side of surface
938 c2i = brep->AddTrimCurve( new ON_LineCurve( p3, p0 ) );
939 ON_BrepTrim& trim3 = brep->NewTrim( e3, f[fi].bRev[3], loop, c2i );
940 trim3.m_tolerance[0] = 0.0;
941 trim3.m_tolerance[1] = 0.0;
942 trim3.m_type = (trim3.m_vi[0] != trim3.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
943 trim3.m_iso = ON_Surface::W_iso;
944 }
945 if ( !brep->IsValid() ) {
946 if ( pBrep )
947 pBrep->Destroy();
948 else
949 delete brep;
950 brep = 0;
951 }
952 }
953 else
954 brep = 0;
955 return brep;
956 }
957
958
ON_BrepWedge(const ON_3dPoint * corners,ON_Brep * pBrep)959 ON_Brep* ON_BrepWedge( const ON_3dPoint* corners, ON_Brep* pBrep )
960 {
961 ON_Brep* brep = 0;
962
963 int vi, ei, ti, fi, si, c2i;
964
965 if(corners)
966 {
967 // use the one passed in or make a new one
968 if( pBrep )
969 {
970 pBrep->Destroy();
971 brep = pBrep;
972 }
973 else
974 brep = new ON_Brep();
975
976 brep->m_C2.Reserve(18);
977 brep->m_C3.Reserve(9);
978 brep->m_S.Reserve(5);
979 brep->m_V.Reserve(6);
980 brep->m_E.Reserve(9);
981 brep->m_L.Reserve(5);
982 brep->m_T.Reserve(18);
983 brep->m_F.Reserve(5);
984
985 // vertices
986 for ( vi = 0; vi < 6; vi++ )
987 {
988 brep->NewVertex( corners[vi], 0.0 );
989 }
990
991 // 3d edges around bottom e0 - e2
992 for ( ei = 0; ei < 3; ei++ )
993 {
994 ON_BrepVertex& v0 = brep->m_V[ei];
995 ON_BrepVertex& v1 = brep->m_V[(ei+1)%3];
996 brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
997 brep->NewEdge( v0, v1, ei, NULL, 0.0 );
998 }
999 // 3d edges around top e3 - e5
1000 for ( ei = 3; ei < 6; ei++ )
1001 {
1002 ON_BrepVertex& v0 = brep->m_V[ei];
1003 ON_BrepVertex& v1 = brep->m_V[ei==5?3:(ei+1)];
1004 brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
1005 brep->NewEdge( v0, v1, ei, NULL, 0.0 );
1006 }
1007 // 3d vertical edges e6 - e8
1008 for ( ei = 6; ei < 9; ei++ )
1009 {
1010 ON_BrepVertex& v0 = brep->m_V[ei-6];
1011 ON_BrepVertex& v1 = brep->m_V[ei-3];
1012 brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
1013 brep->NewEdge( v0, v1, ei, NULL, 0.0 );
1014 }
1015
1016 /*
1017 //
1018 // /v5
1019 // /|\
1020 // / | \
1021 // e5 | e4
1022 // / e8 \
1023 // /__e3_____\
1024 // v3| | |v4
1025 // | | |
1026 // | /v2 |
1027 // e6 / \ e7
1028 // | / \ |
1029 // | e2 e1|
1030 // |/ \|
1031 // /____e0___\
1032 // v0 v1
1033 */
1034
1035 struct {
1036 int e[4], bRev[4];
1037 } f[5] = {
1038 {{0, 7, 3, 6}, {false, false, true, true}}, // vertical front
1039 {{1, 8, 4, 7}, {false, false, true, true}}, // vertical right
1040 {{2, 6, 5, 8}, {false, false, true, true}}, // vertical left
1041 {{2, 1, 0,-1}, {true, true, true, true}}, // bottom
1042 {{3, 4, 5,-1}, {false, false, false, false}} // top
1043 };
1044 for ( fi = 0; fi < 5; fi++ )
1045 {
1046 ON_BrepEdge* e0;
1047 ON_BrepEdge* e1;
1048 ON_BrepEdge* e2;
1049 ON_BrepEdge* e3=0;
1050
1051 e0 = &brep->m_E[f[fi].e[0]];
1052 e1 = &brep->m_E[f[fi].e[1]];
1053 e2 = &brep->m_E[f[fi].e[2]];
1054 if( f[fi].e[3] >= 0)
1055 e3 = &brep->m_E[f[fi].e[3]];
1056
1057 ON_BrepVertex* v0;
1058 ON_BrepVertex* v1;
1059 ON_BrepVertex* v2;
1060 ON_BrepVertex* v3=0;
1061
1062 v0 = &brep->m_V[e0->m_vi[f[fi].bRev[0]?1:0]];
1063 v1 = &brep->m_V[e1->m_vi[f[fi].bRev[1]?1:0]];
1064 v2 = &brep->m_V[e2->m_vi[f[fi].bRev[2]?1:0]];
1065 if( f[fi].e[3] >= 0)
1066 v3 = &brep->m_V[e3->m_vi[f[fi].bRev[3]?1:0]];
1067
1068 ON_NurbsSurface* srf;
1069
1070 if( f[fi].e[3] >= 0)
1071 // 4 sided face
1072 srf = ON_NurbsSurfaceQuadrilateral( v0->point, v1->point, v2->point, v3->point);
1073 else
1074 // 3 sided face
1075 srf = ON_NurbsSurfaceQuadrilateral( v0->point, v1->point, v1->point + (v2->point - v0->point), v2->point);
1076
1077 si = brep->AddSurface( srf);
1078
1079 ON_Interval s = brep->m_S[si]->Domain(0);
1080 ON_Interval t = brep->m_S[si]->Domain(1);
1081 ON_2dPoint p0, p1, p2, p3;
1082 p0.Set(s[0],t[0]);
1083 p1.Set(s[1],t[0]);
1084 p2.Set(s[1],t[1]);
1085 p3.Set(s[0],t[1]);
1086
1087 ON_BrepFace& face = brep->NewFace( si );
1088 ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, face );
1089
1090 if( f[fi].e[3] >= 0)
1091 {
1092 // south side of surface
1093 c2i = brep->AddTrimCurve( new ON_LineCurve( p0, p1 ) );
1094 brep->NewTrim( *e0, f[fi].bRev[0], loop, c2i ).m_iso = ON_Surface::S_iso;
1095
1096 // east side of surface
1097 c2i = brep->AddTrimCurve( new ON_LineCurve( p1, p2 ) );
1098 brep->NewTrim( *e1, f[fi].bRev[1], loop, c2i ).m_iso = ON_Surface::E_iso;
1099
1100 // north side of surface
1101 c2i = brep->AddTrimCurve( new ON_LineCurve( p2, p3 ) );
1102 brep->NewTrim( *e2, f[fi].bRev[2], loop, c2i ).m_iso = ON_Surface::N_iso;
1103
1104 // west side of surface
1105 c2i = brep->AddTrimCurve( new ON_LineCurve( p3, p0 ) );
1106 brep->NewTrim( *e3, f[fi].bRev[3], loop, c2i ).m_iso = ON_Surface::W_iso;
1107 }
1108 else
1109 {
1110 // south side of surface
1111 c2i = brep->AddTrimCurve( new ON_LineCurve( p0, p1 ) );
1112 brep->NewTrim( *e0, f[fi].bRev[0], loop, c2i ).m_iso = ON_Surface::S_iso;
1113
1114 // diagonal from upper left to lower right
1115 c2i = brep->AddTrimCurve( new ON_LineCurve( p1, p3 ) );
1116 brep->NewTrim( *e1, f[fi].bRev[1], loop, c2i ).m_iso = ON_Surface::not_iso;
1117
1118 // west side of surface
1119 c2i = brep->AddTrimCurve( new ON_LineCurve( p3, p0 ) );
1120 brep->NewTrim( *e2, f[fi].bRev[2], loop, c2i ).m_iso = ON_Surface::W_iso;
1121 }
1122 }
1123
1124 // set trim m_type and m_tolerance[]
1125 for ( ti = 0; ti < brep->m_T.Count(); ti++ )
1126 {
1127 ON_BrepTrim& trim = brep->m_T[ti];
1128 trim.m_type = ( trim.m_vi[0] != trim.m_vi[1] && trim.m_ei >= 0 )
1129 ? ON_BrepTrim::mated
1130 : ON_BrepTrim::singular;
1131 trim.m_tolerance[0] = 0.0;
1132 trim.m_tolerance[1] = 0.0;
1133 }
1134
1135 if ( !brep->IsValid() ) {
1136 if ( pBrep )
1137 pBrep->Destroy();
1138 else
1139 delete brep;
1140 brep = 0;
1141 }
1142 }
1143 else
1144 brep = 0;
1145 return brep;
1146 }
1147
1148
ON_BrepSphere(const ON_Sphere & sphere,ON_Brep * pBrep)1149 ON_Brep* ON_BrepSphere( const ON_Sphere& sphere, ON_Brep* pBrep )
1150 {
1151 bool bArcLengthParameterization = true;
1152 ON_Brep* brep = NULL;
1153 if ( pBrep )
1154 pBrep->Destroy();
1155 ON_RevSurface* pRevSurface = sphere.RevSurfaceForm(bArcLengthParameterization);
1156 if ( pRevSurface )
1157 {
1158 brep = ON_BrepRevSurface( pRevSurface, false, false, pBrep );
1159 if ( !brep )
1160 delete pRevSurface;
1161 }
1162 return brep;
1163 }
1164
1165
ON_BrepTorus(const ON_Torus & torus,ON_Brep * pBrep)1166 ON_Brep* ON_BrepTorus( const ON_Torus& torus, ON_Brep* pBrep )
1167 {
1168 ON_BOOL32 bArcLengthParameterization = true;
1169 ON_Brep* brep = NULL;
1170 if ( pBrep )
1171 pBrep->Destroy();
1172 ON_RevSurface* pRevSurface = torus.RevSurfaceForm();
1173 if ( pRevSurface )
1174 {
1175 if ( bArcLengthParameterization )
1176 {
1177 double r = fabs(torus.major_radius);
1178 if ( r <= ON_SQRT_EPSILON )
1179 r = 1.0;
1180 r *= ON_PI;
1181 pRevSurface->SetDomain(0,0.0,2.0*r);
1182 r = fabs(torus.minor_radius);
1183 if ( r <= ON_SQRT_EPSILON )
1184 r = 1.0;
1185 r *= ON_PI;
1186 pRevSurface->SetDomain(1,0.0,2.0*r);
1187 }
1188 brep = ON_BrepRevSurface( pRevSurface, false, false, pBrep );
1189 if ( !brep )
1190 delete pRevSurface;
1191 }
1192 return brep;
1193 }
1194
1195
ON_BrepCylinder(const ON_Cylinder & cylinder,ON_BOOL32 bCapBottom,ON_BOOL32 bCapTop,ON_Brep * pBrep)1196 ON_Brep* ON_BrepCylinder( const ON_Cylinder& cylinder,
1197 ON_BOOL32 bCapBottom,
1198 ON_BOOL32 bCapTop,
1199 ON_Brep* pBrep )
1200 {
1201 ON_BOOL32 bArcLengthParameterization = true;
1202 ON_Brep* brep = NULL;
1203 if ( pBrep )
1204 pBrep->Destroy();
1205 ON_RevSurface* pRevSurface = cylinder.RevSurfaceForm();
1206 if ( pRevSurface )
1207 {
1208 if ( bArcLengthParameterization )
1209 {
1210 double r = fabs(cylinder.circle.radius);
1211 if ( r <= ON_SQRT_EPSILON )
1212 r = 1.0;
1213 pRevSurface->SetDomain(0,0.0,2.0*ON_PI*r);
1214 }
1215 brep = ON_BrepRevSurface( pRevSurface, bCapBottom, bCapTop, pBrep );
1216 if ( !brep )
1217 delete pRevSurface;
1218 }
1219 return brep;
1220 }
1221
1222
ON_BrepCone(const ON_Cone & cone,ON_BOOL32 bCapBase,ON_Brep * pBrep)1223 ON_Brep* ON_BrepCone( const ON_Cone& cone, ON_BOOL32 bCapBase, ON_Brep* pBrep )
1224 {
1225 ON_BOOL32 bArcLengthParameterization = true;
1226 ON_Brep* brep = NULL;
1227 if ( pBrep )
1228 pBrep->Destroy();
1229 ON_RevSurface* pRevSurface = cone.RevSurfaceForm();
1230 if ( pRevSurface )
1231 {
1232 if ( bArcLengthParameterization )
1233 {
1234 double r = fabs(cone.radius);
1235 if ( r <= ON_SQRT_EPSILON )
1236 r = 1.0;
1237 pRevSurface->SetDomain(0,0.0,2.0*ON_PI*r);
1238 }
1239 brep = ON_BrepRevSurface( pRevSurface, bCapBase, bCapBase, pBrep );
1240 if ( !brep )
1241 delete pRevSurface;
1242 }
1243 return brep;
1244 }
1245
1246
ON_BrepRevSurface(ON_RevSurface * & pRevSurface,ON_BOOL32 bCapStart,ON_BOOL32 bCapEnd,ON_Brep * pBrep)1247 ON_Brep* ON_BrepRevSurface(
1248 ON_RevSurface*& pRevSurface,
1249 ON_BOOL32 bCapStart,
1250 ON_BOOL32 bCapEnd,
1251 ON_Brep* pBrep
1252 )
1253 {
1254 ON_Brep* brep = 0;
1255 if ( pBrep )
1256 pBrep->Destroy();
1257 if ( pRevSurface && pRevSurface->m_curve )
1258 {
1259 if ( pBrep )
1260 brep = pBrep;
1261 else
1262 brep = new ON_Brep();
1263
1264 ON_BOOL32 bTransposed = pRevSurface->m_bTransposed;
1265 ON_Line axis = pRevSurface->m_axis;
1266 ON_3dPoint R[2];
1267 R[0] = pRevSurface->m_curve->PointAtStart();
1268 R[1] = pRevSurface->m_curve->PointAtEnd();
1269 if ( !pRevSurface->IsClosed(bTransposed?1:0) )
1270 {
1271 bCapStart = false;
1272 bCapEnd = false;
1273 }
1274
1275 if ( !brep->Create(pRevSurface) )
1276 {
1277 if (pBrep != brep)
1278 delete brep;
1279 brep = 0;
1280 }
1281 else if ( bCapStart || bCapEnd )
1282 {
1283 // cap ends
1284 for ( int capcount = 0; capcount < 2; capcount++ )
1285 {
1286 int srf_trim_ti = -1;
1287 // capcount = 0 for bottom cap and 1 for top cap
1288 if ( capcount == 0 )
1289 {
1290 // cap circle at start of revolute
1291 if ( !bCapStart )
1292 continue;
1293 srf_trim_ti = (bTransposed) ? 3 : 0;
1294 }
1295 else
1296 {
1297 // cap circle at start of revolute
1298 if ( !bCapEnd )
1299 continue;
1300 srf_trim_ti = (bTransposed) ? 1 : 2;
1301 }
1302 if ( srf_trim_ti < 0 || srf_trim_ti >= brep->m_T.Count() )
1303 continue;
1304
1305 if ( brep->m_T[srf_trim_ti].m_type != ON_BrepTrim::boundary )
1306 continue;
1307 if ( brep->m_T[srf_trim_ti].m_ei < 0 )
1308 continue;
1309 ON_BrepEdge& edge = brep->m_E[brep->m_T[srf_trim_ti].m_ei];
1310 if ( !edge.IsClosed() )
1311 continue;
1312
1313 ON_Circle circle;
1314 {
1315 ON_Arc arc;
1316 const ON_Curve* edge_curve = edge.EdgeCurveOf();
1317 if ( 0 == edge_curve )
1318 continue;
1319 if ( !edge_curve->IsArc( NULL, &arc ) )
1320 continue;
1321 if ( !arc.IsCircle() )
1322 continue;
1323 circle = arc;
1324 }
1325
1326 /*
1327 if ( capcount == 0 )
1328 circle.Reverse();
1329 */
1330 circle.Reverse();
1331
1332 // create cap surface
1333 double radius = circle.radius;
1334 ON_NurbsSurface* pCapSurface = ON_NurbsSurfaceQuadrilateral(
1335 circle.plane.PointAt(-radius,-radius),
1336 circle.plane.PointAt(+radius,-radius),
1337 circle.plane.PointAt(+radius,+radius),
1338 circle.plane.PointAt(-radius,+radius)
1339 );
1340 pCapSurface->m_knot[0][0] = -fabs(radius);
1341 pCapSurface->m_knot[0][1] = fabs(radius);
1342 pCapSurface->m_knot[1][0] = pCapSurface->m_knot[0][0];
1343 pCapSurface->m_knot[1][1] = pCapSurface->m_knot[0][1];
1344
1345 // trim curve circle
1346 circle.Create( ON_xy_plane, ON_origin, radius );
1347 ON_NurbsCurve* c2 = new ON_NurbsCurve();
1348 circle.GetNurbForm(*c2);
1349 c2->ChangeDimension(2);
1350
1351 int si = brep->AddSurface(pCapSurface);
1352 int c2i = brep->AddTrimCurve(c2);
1353 ON_BrepFace& cap = brep->NewFace( si );
1354 ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, cap );
1355 ON_BrepTrim& trim = brep->NewTrim( edge, true, loop, c2i );
1356 for ( int eti = 0; eti < edge.m_ti.Count(); eti++ )
1357 brep->m_T[ edge.m_ti[eti] ].m_type = ON_BrepTrim::mated;
1358 trim.m_tolerance[0] = 0.0;
1359 trim.m_tolerance[1] = 0.0;
1360 trim.m_pbox.m_min.x = -radius;
1361 trim.m_pbox.m_min.y = -radius;
1362 trim.m_pbox.m_min.z = 0.0;
1363 trim.m_pbox.m_max.x = radius;
1364 trim.m_pbox.m_max.y = radius;
1365 trim.m_pbox.m_max.z = 0.0;
1366 trim.m__legacy_2d_tol = 0.0;
1367 trim.m__legacy_3d_tol = 0.0;
1368 loop.m_pbox = trim.m_pbox;
1369 brep->SetTrimTypeFlags(trim);
1370 brep->SetTrimIsoFlags(trim);
1371 }
1372 }
1373 }
1374 return brep;
1375 }
1376
1377
1378
AddC3Curve(const ON_Curve * c3,ON_SimpleArray<ON_Curve * > & C3)1379 static ON_BOOL32 AddC3Curve( const ON_Curve* c3, ON_SimpleArray<ON_Curve*>& C3 )
1380 {
1381 int j;
1382 if ( !c3 )
1383 return false;
1384 const int c3dim = c3->Dimension();
1385 if ( c3dim != 3 && c3dim != 2 )
1386 return false;
1387 if ( ON_PolyCurve::Cast(c3) )
1388 {
1389 const ON_PolyCurve* polycrv = static_cast<const ON_PolyCurve*>(c3);
1390 for ( j = 0; j < polycrv->Count(); j++ )
1391 {
1392 if ( !AddC3Curve( polycrv->SegmentCurve(j), C3 ) )
1393 return false;
1394 }
1395 }
1396 else if ( ON_PolylineCurve::Cast(c3) )
1397 {
1398 ON_Line line;
1399 //ON_LineCurve* linecrv = 0;
1400 const ON_PolylineCurve* pline = static_cast<const ON_PolylineCurve*>(c3);
1401 line.to = pline->m_pline[0];
1402 if ( 2 == c3dim )
1403 line.to.z = 0.0;
1404 for ( j = 1; j < pline->m_pline.Count(); j++ )
1405 {
1406 line.from = line.to;
1407 line.to = pline->m_pline[j];
1408 if ( 2 == c3dim )
1409 line.to.z = 0.0;
1410 if ( line.Length() > 0 )
1411 C3.Append( new ON_LineCurve(line) );
1412 }
1413 }
1414 else
1415 {
1416 ON_Curve* c3dup = c3->DuplicateCurve();
1417 if ( 0 == c3dup )
1418 return false;
1419 if ( 2 == c3dup->Dimension() )
1420 {
1421 c3dup->ChangeDimension(3);
1422 if ( 3 != c3dup->Dimension() )
1423 {
1424 delete c3dup;
1425 return false;
1426 }
1427 }
1428 C3.Append( c3dup );
1429 }
1430 return true;
1431 }
1432
NewPlanarFaceLoop(int face_index,ON_BrepLoop::TYPE loop_type,ON_SimpleArray<ON_Curve * > & boundary,ON_BOOL32 bDuplicateCurves)1433 bool ON_Brep::NewPlanarFaceLoop(
1434 int face_index,
1435 ON_BrepLoop::TYPE loop_type,
1436 ON_SimpleArray<ON_Curve*>& boundary,
1437 ON_BOOL32 bDuplicateCurves
1438 )
1439 {
1440 m_is_solid = 0;
1441 if ( face_index < 0 || face_index >= m_F.Count() || boundary.Count() < 1 )
1442 return false;
1443 ON_BrepFace& face = m_F[face_index];
1444 const ON_PlaneSurface* pPlaneSurface = ON_PlaneSurface::Cast(face.SurfaceOf());
1445 if ( !pPlaneSurface )
1446 return false;
1447 const ON_Plane plane(pPlaneSurface->m_plane);
1448
1449 // get 3d edge curves
1450 ON_SimpleArray<ON_Curve*> C3( 2*boundary.Count() );
1451 ON_Curve* c3;
1452 int i, count = boundary.Count();
1453 for ( i = 0; i < count; i++ )
1454 {
1455 c3 = boundary[i];
1456 if ( !c3 )
1457 break;
1458 if ( bDuplicateCurves )
1459 {
1460 if ( !AddC3Curve( c3, C3 ) )
1461 break;
1462 }
1463 else
1464 {
1465 C3.Append(c3);
1466 boundary[i] = 0;
1467 }
1468 }
1469
1470 if ( i < count )
1471 {
1472 ON_ERROR("ON_Brep::NewPlanarFaceLoop - null 3d curve in boundary[] array");
1473 if ( bDuplicateCurves )
1474 {
1475 for ( i = 0; i < C3.Count(); i++ )
1476 delete C3[i];
1477 }
1478 else
1479 {
1480 for ( i = 0; i < C3.Count(); i++ )
1481 boundary[i] = C3[i];
1482 }
1483 return false;
1484 }
1485
1486 // get 2d trim curves
1487 ON_Xform proj_to_plane;
1488 proj_to_plane[0][0] = plane.xaxis.x;
1489 proj_to_plane[0][1] = plane.xaxis.y;
1490 proj_to_plane[0][2] = plane.xaxis.z;
1491 proj_to_plane[0][3] = -(plane.xaxis*plane.origin);
1492 proj_to_plane[1][0] = plane.yaxis.x;
1493 proj_to_plane[1][1] = plane.yaxis.y;
1494 proj_to_plane[1][2] = plane.yaxis.z;
1495 proj_to_plane[1][3] = -(plane.yaxis*plane.origin);
1496 proj_to_plane[2][0] = plane.zaxis.x;
1497 proj_to_plane[2][1] = plane.zaxis.y;
1498 proj_to_plane[2][2] = plane.zaxis.z;
1499 proj_to_plane[2][3] = -(plane.zaxis*plane.origin);
1500 proj_to_plane[3][0] = 0.0;
1501 proj_to_plane[3][1] = 0.0;
1502 proj_to_plane[3][2] = 0.0;
1503 proj_to_plane[3][3] = 1.0;
1504
1505 count = C3.Count();
1506 ON_BoundingBox loop_pbox, cbox;
1507 ON_SimpleArray<double> edge_tol(count);
1508 ON_SimpleArray<ON_NurbsCurve*> C2( count );
1509 ON_NurbsCurve* c2;
1510 for ( i = 0; i < count; i++ )
1511 {
1512 c3 = C3[i];
1513 c2 = new ON_NurbsCurve();
1514 if ( !c3->GetNurbForm(*c2) )
1515 break;
1516 if ( !c2->Transform(proj_to_plane) )
1517 break;
1518 if ( !c2->GetBoundingBox(cbox) )
1519 break;
1520 double d = fabs(cbox.m_max.z);
1521 if ( d < fabs(cbox.m_min.z) )
1522 d = fabs(cbox.m_min.z);
1523 if ( d <= ON_ZERO_TOLERANCE )
1524 d = 0.0;
1525 edge_tol.Append( d );
1526 if ( !c2->ChangeDimension(2) )
1527 break;
1528 if ( !c2->MakePiecewiseBezier() )
1529 break;
1530 cbox.m_min.z = 0.0;
1531 cbox.m_max.z = 0.0;
1532 loop_pbox.Union(cbox);
1533 C2.Append(c2);
1534 }
1535 if ( i < count )
1536 {
1537 ON_ERROR("ON_Brep::NewPlanarFaceLoop - unable to create 2d trim curve");
1538 for ( i = 0; i < C2.Count(); i++ )
1539 delete C2[i];
1540 for ( i = 0; i < C3.Count(); i++ )
1541 delete C3[i];
1542 return false;
1543 }
1544
1545 // add new vertices
1546 const int vi0 = m_V.Count();
1547 m_V.Reserve( vi0 + count );
1548 for ( i = 0; i < count; i++ )
1549 NewVertex( C3[i]->PointAtStart() );
1550
1551 // add new edges
1552 const int ei0 = m_E.Count();
1553 m_E.Reserve( ei0 + count );
1554 for ( i = 0; i < count; i++ )
1555 {
1556 int c3i = AddEdgeCurve( C3[i] );
1557 ON_BrepEdge& edge = NewEdge( m_V[vi0+i], m_V[vi0+((i+1)%count)], c3i );
1558 edge.m_tolerance = edge_tol[i];
1559 }
1560
1561 // add new trims
1562 ON_3dPoint P, Q;
1563 double trim_tol[2];
1564 ON_BrepLoop& loop = NewLoop( loop_type, face );
1565 loop.m_pbox = loop_pbox;
1566 for (i = 0; i < count; i++)
1567 {
1568 int c2i = AddTrimCurve( C2[i] );
1569 trim_tol[0] = 0.0;
1570 trim_tol[1] = 0.0;
1571 ON_NurbsCurve* c2 = C2[i];
1572 P = c2->PointAtEnd();
1573 Q = C2[(i+1)%count]->PointAtStart();
1574 double w = (c2->IsRational()) ? c2->Weight(c2->m_cv_count-1) : 1.0;
1575 if (w < ON_ZERO_TOLERANCE)
1576 w = 1.0;
1577 if (c2->IsRational())
1578 Q *= w;
1579 c2->SetCV( c2->m_cv_count-1, Q );
1580 if (c2->IsRational())
1581 c2->SetWeight(c2->m_cv_count-1, w);
1582 trim_tol[0] = fabs(P.x - Q.x);
1583 trim_tol[1] = fabs(P.y - Q.y);
1584 if ( trim_tol[0] <= ON_ZERO_TOLERANCE )
1585 trim_tol[0] = 0.0;
1586 if ( trim_tol[1] <= ON_ZERO_TOLERANCE )
1587 trim_tol[1] = 0.0;
1588 ON_BrepEdge& edge = m_E[ei0+i];
1589 ON_BrepTrim& trim = NewTrim( edge, false, loop, c2i );
1590 trim.m_type = ON_BrepTrim::boundary;
1591 trim.m_tolerance[0] = 1.1*trim_tol[0];
1592 trim.m_tolerance[1] = 1.1*trim_tol[1];
1593 }
1594 int loop_dir = LoopDirection( loop );
1595 switch ( loop_type )
1596 {
1597 case ON_BrepLoop::outer:
1598 if ( loop_dir < 0 )
1599 FlipLoop( loop );
1600 break;
1601 case ON_BrepLoop::inner:
1602 if ( loop_dir > 0 )
1603 FlipLoop( loop );
1604 break;
1605 case ON_BrepLoop::unknown:
1606 if ( loop_dir > 0 )
1607 loop.m_type = ON_BrepLoop::outer;
1608 else if ( loop_dir < 0 )
1609 loop.m_type = ON_BrepLoop::inner;
1610 break;
1611 default:
1612 // intentionally ignoring other ON_Brep::TYPE enum values
1613 break;
1614 }
1615
1616 SetTrimIsoFlags();
1617 for ( i = vi0; i < m_V.Count(); i++ )
1618 SetVertexTolerance( m_V[i] );
1619
1620 return true;
1621 }
1622
1623
ON_BrepTrimmedPlane(const ON_Plane & plane,ON_SimpleArray<ON_Curve * > & boundary,ON_BOOL32 bDuplicateCurves,ON_Brep * pBrep)1624 ON_Brep* ON_BrepTrimmedPlane(
1625 const ON_Plane& plane,
1626 ON_SimpleArray<ON_Curve*>& boundary,
1627 ON_BOOL32 bDuplicateCurves,
1628 ON_Brep* pBrep )
1629 {
1630 ON_Brep* brep;
1631 if ( pBrep )
1632 {
1633 pBrep->Destroy();
1634 brep = pBrep;
1635 }
1636 else
1637 brep = new ON_Brep();
1638
1639 ON_PlaneSurface* s = new ON_PlaneSurface();
1640 s->m_plane = plane;
1641 s->SetDomain(0, -100.0, 100.0 ); // any domain and extents will do for now
1642 s->SetDomain(1, -100.0, 100.0 );
1643 s->SetExtents(0, s->Domain(0) );
1644 s->SetExtents(1, s->Domain(1) );
1645 const int si = brep->AddSurface(s);
1646 ON_BrepFace& face = brep->NewFace( si );
1647 face.DestroyRuntimeCache();
1648 if ( brep->NewPlanarFaceLoop( face.m_face_index, ON_BrepLoop::outer, boundary, bDuplicateCurves ) )
1649 {
1650 // set face domain
1651 const ON_BrepLoop* loop = brep->m_L.Last();
1652 s->SetDomain(0, loop->m_pbox.m_min.x, loop->m_pbox.m_max.x );
1653 s->SetDomain(1, loop->m_pbox.m_min.y, loop->m_pbox.m_max.y );
1654 s->SetExtents(0,s->Domain(0));
1655 s->SetExtents(1,s->Domain(1));
1656
1657 // need to update trim m_iso flags because we changed surface shape
1658 brep->SetTrimIsoFlags(face);
1659 }
1660 else
1661 {
1662 if ( pBrep )
1663 pBrep->Destroy();
1664 else
1665 delete brep;
1666 brep = NULL;
1667 }
1668 return brep;
1669 }
1670
1671
1672
ON_BrepTrimmedPlane(const ON_Plane & plane,const ON_Curve & boundary,ON_Brep * pBrep)1673 ON_Brep* ON_BrepTrimmedPlane(
1674 const ON_Plane& plane,
1675 const ON_Curve& boundary,
1676 ON_Brep* pBrep )
1677 {
1678 ON_SimpleArray<ON_Curve*> c;
1679 c.Append(const_cast<ON_Curve*>(&boundary));
1680 return ON_BrepTrimmedPlane( plane, c, true, pBrep );
1681 }
1682
1683
ON_BrepFromMesh(const ON_MeshTopology & mesh_topology,ON_BOOL32 bTrimmedTriangles,ON_Brep * pBrep)1684 ON_Brep* ON_BrepFromMesh(
1685 const ON_MeshTopology& mesh_topology,
1686 ON_BOOL32 bTrimmedTriangles,
1687 ON_Brep* pBrep
1688 )
1689 {
1690 ON_BezierCurve edge_line(3,false,2);
1691 ON_BezierCurve trim_line(2,false,2);
1692 ON_Brep* brep = NULL;
1693 if ( pBrep )
1694 pBrep->Destroy();
1695 if ( mesh_topology.m_mesh && mesh_topology.IsValid() )
1696 {
1697 //const ON_Mesh& mesh = *mesh_topology.m_mesh;
1698 brep = (pBrep != NULL) ? pBrep : new ON_Brep();
1699 const int vertex_count = mesh_topology.TopVertexCount();
1700 const int edge_count = mesh_topology.TopEdgeCount();
1701 const int face_count = mesh_topology.TopFaceCount();
1702 brep->m_V.Reserve( vertex_count );
1703 brep->m_E.Reserve( edge_count );
1704 brep->m_C3.Reserve( edge_count );
1705 brep->m_F.Reserve( face_count );
1706 brep->m_L.Reserve( face_count );
1707 brep->m_T.Reserve( 4*face_count );
1708 brep->m_C2.Reserve( 4*face_count );
1709
1710 int vi, ei, fi, c3i, c2i, si, lti, fvi[4];
1711 ON_Interval srf_dom[2];
1712 ON_3dPoint srf_2d_corner[4];
1713 ON_3dPoint srf_3d_corner[4];
1714 ON_Surface::ISO quad_iso[4] = {ON_Surface::S_iso,ON_Surface::E_iso,ON_Surface::N_iso,ON_Surface::W_iso};
1715 ON_Surface::ISO tri_iso[3] = {ON_Surface::S_iso,ON_Surface::E_iso,ON_Surface::not_iso};
1716
1717 // May 1, 2012 Tim Fix for RR 104209
1718 // Use double precision vertexes from the mesh if they exist
1719 const ON_3dPointArray* pDPV = 0;
1720 if (mesh_topology.m_mesh->HasDoublePrecisionVertices() && mesh_topology.m_mesh->DoublePrecisionVerticesAreValid())
1721 pDPV = &mesh_topology.m_mesh->DoublePrecisionVertices();
1722
1723 for ( vi = 0; vi < vertex_count; vi++ )
1724 {
1725 ON_3dPoint pt;
1726
1727 // May 1, 2012 Tim Fix for RR 104209
1728 // Use double precision vertexes from the mesh if they exist
1729 const ON_MeshTopologyVertex& topvert = mesh_topology.m_topv[vi];
1730 if (0 != pDPV)
1731 pt = *pDPV->At(topvert.m_vi[0]);
1732 else
1733 pt = mesh_topology.m_mesh->m_V[topvert.m_vi[0]];
1734
1735 brep->NewVertex( pt, 0.0 );
1736 }
1737
1738 for ( ei = 0; ei < edge_count; ei++ )
1739 {
1740 const ON_MeshTopologyEdge& mesh_edge = mesh_topology.m_tope[ei];
1741 ON_BrepVertex& v0 = brep->m_V[mesh_edge.m_topvi[0]];
1742 ON_BrepVertex& v1 = brep->m_V[mesh_edge.m_topvi[1]];
1743 edge_line.SetCV(0, v0.point);
1744 edge_line.SetCV(1, v1.point);
1745 ON_Curve* pEdgeCurve = new ON_NurbsCurve( edge_line );
1746 c3i = brep->AddEdgeCurve( pEdgeCurve );
1747 ON_BrepEdge& edge = brep->NewEdge( v0, v1, c3i );
1748 edge.m_tolerance = 0.0;
1749 }
1750
1751 for ( fi = 0; fi < face_count; fi++ )
1752 {
1753 const ON_MeshTopologyFace& mesh_face = mesh_topology.m_topf[fi];
1754 // NOTE: mesh_face.m_topei[0] ENDS at vertex fvi[0].
1755 mesh_topology.GetTopFaceVertices( fi, fvi );
1756 ON_BOOL32 bTriangle = mesh_face.IsTriangle();
1757 srf_3d_corner[0] = brep->m_V[fvi[0]].point;
1758 srf_3d_corner[1] = brep->m_V[fvi[1]].point;
1759 srf_3d_corner[2] = brep->m_V[fvi[2]].point;
1760 if ( bTriangle )
1761 {
1762 if ( bTrimmedTriangles )
1763 {
1764 // trimmed triangle
1765 srf_3d_corner[3] = srf_3d_corner[2] - srf_3d_corner[1] + srf_3d_corner[0];
1766 }
1767 else
1768 {
1769 // singular triangle
1770 srf_3d_corner[3] = srf_3d_corner[0];
1771 }
1772 }
1773 else
1774 {
1775 // quad
1776 srf_3d_corner[3] = brep->m_V[fvi[3]].point;
1777 }
1778 ON_Surface* pSurface = ON_NurbsSurfaceQuadrilateral(
1779 srf_3d_corner[0], srf_3d_corner[1],
1780 srf_3d_corner[2], srf_3d_corner[3] );
1781 srf_dom[0] = pSurface->Domain(0);
1782 srf_dom[1] = pSurface->Domain(1);
1783 srf_2d_corner[0].Set( srf_dom[0][0], srf_dom[1][0], 0.0 ); // SW parameter space corner
1784 srf_2d_corner[1].Set( srf_dom[0][1], srf_dom[1][0], 0.0 ); // SE parameter space corner
1785 srf_2d_corner[2].Set( srf_dom[0][1], srf_dom[1][1], 0.0 ); // NE parameter space corner
1786 srf_2d_corner[3].Set( srf_dom[0][0], srf_dom[1][1], 0.0 ); // NW parameter space corner
1787 si = brep->AddSurface( pSurface );
1788 ON_BrepFace& face = brep->NewFace( si );
1789 ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, face );
1790 loop.m_pbox.m_min = srf_2d_corner[0];
1791 loop.m_pbox.m_max = srf_2d_corner[2];
1792
1793 int edge_index;
1794 int fei;
1795 if ( bTriangle && bTrimmedTriangles )
1796 {
1797 // trimmed triangle
1798 for ( lti = 0; lti < 3; lti++ )
1799 {
1800 fei = (lti+1)%3;
1801 edge_index = mesh_face.m_topei[fei];
1802 ON_BrepEdge& brep_edge = brep->m_E[edge_index];
1803 const ON_MeshTopologyEdge& mesh_edge = mesh_topology.m_tope[edge_index];
1804 trim_line.SetCV(0,srf_2d_corner[lti]);
1805 trim_line.SetCV(1,srf_2d_corner[(lti+1)%3]);
1806 ON_Curve* pTrimCurve = new ON_NurbsCurve( trim_line );
1807 c2i = brep->AddTrimCurve( pTrimCurve );
1808 ON_BrepTrim& trim = brep->NewTrim( brep_edge,
1809 mesh_face.m_reve[fei]?true:false,
1810 loop,
1811 c2i );
1812 trim.m__legacy_2d_tol = 0.0;
1813 trim.m__legacy_3d_tol = 0.0;
1814 trim.m_tolerance[0] = 0.0;
1815 trim.m_tolerance[1] = 0.0;
1816 trim.m_iso = tri_iso[lti];
1817 trim.m_type = (mesh_edge.m_topf_count > 1) ? ON_BrepTrim::mated : ON_BrepTrim::boundary;
1818 }
1819 }
1820 else
1821 {
1822 for ( lti = 0; lti < 4; lti++ )
1823 {
1824 trim_line.SetCV(0,srf_2d_corner[lti]);
1825 trim_line.SetCV(1,srf_2d_corner[(lti+1)%4]);
1826 ON_Curve* c2 = new ON_NurbsCurve( trim_line );
1827 c2i = brep->AddTrimCurve( c2 );
1828 if ( bTriangle && lti == 3 )
1829 {
1830 // build a new singular edge
1831 brep->NewSingularTrim( brep->m_V[fvi[0]],
1832 loop,
1833 quad_iso[lti],
1834 c2i );
1835 }
1836 else
1837 {
1838 fei = bTriangle ? ((lti+1)%3) : ((lti+1)%4);
1839 edge_index = mesh_face.m_topei[fei];
1840 ON_BrepEdge& brep_edge = brep->m_E[edge_index];
1841 const ON_MeshTopologyEdge& mesh_edge = mesh_topology.m_tope[edge_index];
1842 ON_BrepTrim& trim = brep->NewTrim( brep_edge,
1843 mesh_face.m_reve[fei]?true:false,
1844 loop,
1845 c2i );
1846 trim.m__legacy_2d_tol = 0.0;
1847 trim.m__legacy_3d_tol = 0.0;
1848 trim.m_tolerance[0] = 0.0;
1849 trim.m_tolerance[1] = 0.0;
1850 trim.m_iso = quad_iso[lti];
1851 trim.m_type = (mesh_edge.m_topf_count > 1) ? ON_BrepTrim::mated : ON_BrepTrim::boundary;
1852 }
1853 }
1854 }
1855 }
1856 }
1857 return brep;
1858 }
1859
FoundSlitPair(ON_BrepLoop & L,int * t0,int * t1)1860 static bool FoundSlitPair(ON_BrepLoop& L, int* t0, int* t1)
1861
1862 {
1863 ON_Brep* B = L.Brep();
1864 if (!B) return false;
1865 const ON_Surface* Srf = L.SurfaceOf();
1866 double utol = 0.1*Srf->Domain(0).Length();
1867 double vtol = 0.1*Srf->Domain(1).Length();
1868 if (!Srf) return false;
1869 int i, count = L.m_ti.Count();
1870 for (i=0; i<count; i++){
1871 int s0 = L.m_ti[i];
1872 ON_BrepTrim& T0 = B->m_T[s0];
1873 if (T0.m_type != ON_BrepTrim::seam) continue;
1874 int s1 = (L.m_ti[(i+1)%count]);
1875 ON_BrepTrim& T1 = B->m_T[s1];
1876 if (T1.m_type != ON_BrepTrim::seam) continue;
1877 if (T0.m_vi[0] != T1.m_vi[1]) continue;
1878 if (T0.m_ei != T1.m_ei) continue;
1879 const ON_BrepEdge& E = B->m_E[T0.m_ei];
1880 if (E.m_ti.Count() != 2) continue;
1881 ON_2dPoint P0, P1;
1882 if (!B->GetTrim2dStart(s0, P0)) continue;
1883 if (!B->GetTrim2dEnd(s1, P1)) continue;
1884 if (fabs(P0[0] - P1[0]) > utol || fabs(P0[1] - P1[1]) > vtol) continue;
1885 *t0 = s0;
1886 *t1 = s1;
1887 return true;
1888 }
1889
1890 return false;
1891
1892 }
1893
1894
RemoveSlits(ON_BrepFace & F)1895 bool ON_Brep::RemoveSlits(ON_BrepFace& F)
1896
1897 {
1898 int i;
1899 bool rc = false;
1900 ON_SimpleArray<int> li = F.m_li;
1901 for (i=0; i<li.Count(); i++){
1902 ON_BrepLoop& L = m_L[li[i]];
1903 if (L.m_loop_index != li[i]) continue;
1904 if (L.m_type == ON_BrepLoop::slit) {
1905 DeleteLoop(L, true);
1906 rc = true;
1907 continue;
1908 }
1909 int t0, t1;
1910 while (FoundSlitPair(L, &t0, &t1)){
1911 rc = true;
1912 DeleteTrim(m_T[t0], true);
1913 DeleteTrim(m_T[t1], true);
1914 }
1915 if (L.m_ti.Count() == 0) DeleteLoop(L, true);
1916 }
1917 return rc;
1918 }
1919
1920
1921
RemoveSlits()1922 bool ON_Brep::RemoveSlits()
1923
1924 {
1925 bool rc = false;
1926 int i;
1927 for (i=0; i<m_F.Count(); i++){
1928 ON_BrepFace& F = m_F[i];
1929 if (F.m_face_index != i) continue;
1930 if (RemoveSlits(F))
1931 rc = true;
1932 }
1933 return rc;
1934 }
1935
ChangeVertex(int old_vi,int new_vi,bool bClearTolerances)1936 bool ON_Brep::ChangeVertex( int old_vi, int new_vi, bool bClearTolerances )
1937 {
1938 if ( old_vi == new_vi )
1939 return true;
1940
1941 ON_BrepVertex* old_v = Vertex(old_vi);
1942 ON_BrepVertex* new_v = Vertex(new_vi);
1943
1944 if ( 0 == old_v )
1945 return false;
1946 if ( 0 == new_v )
1947 return false;
1948 if( old_v == new_v )
1949 return true;
1950
1951 // clear type bits
1952 old_vi = (int)(old_v - m_V.Array()); // the (int) is for 64 bit size_t conversion
1953 new_vi = (int)(new_v - m_V.Array());
1954 if ( old_vi == new_vi )
1955 return true;
1956
1957 int vei, evi, eti, tvi, ei;
1958
1959 for ( vei = 0; vei < old_v->m_ei.Count(); vei++ )
1960 {
1961 ei = old_v->m_ei[vei];
1962 ON_BrepEdge* edge = Edge( ei );
1963 if ( 0 == edge )
1964 continue;
1965 // edges that start/end at the same vertex are listed twice in old_v->m_ei[].
1966 if ( edge->m_vi[0] == old_v->m_vertex_index )
1967 evi = 0;
1968 else if ( edge->m_vi[1] == old_v->m_vertex_index )
1969 evi = 1;
1970 else
1971 continue;
1972
1973 // connect edge to new vertex
1974 new_v->m_ei.Append(ei);
1975 edge->m_vi[evi] = new_vi;
1976 if ( bClearTolerances )
1977 {
1978 edge->m_tolerance = ON_UNSET_VALUE;
1979 new_v->m_tolerance = ON_UNSET_VALUE;
1980 }
1981
1982 for ( eti = 0; eti < edge->m_ti.Count(); eti++ )
1983 {
1984 ON_BrepTrim* trim = Trim( edge->m_ti[eti]);
1985 if ( 0 == trim )
1986 continue;
1987 tvi = trim->m_bRev3d ? 1-evi : evi;
1988 trim->m_vi[tvi] = new_vi;
1989 for(;;)
1990 {
1991 if ( 0 == tvi )
1992 trim = Trim(PrevTrim(trim->m_trim_index));
1993 else if ( 1 == tvi )
1994 trim = Trim(NextTrim(trim->m_trim_index));
1995 else
1996 break;
1997
1998 if ( 0 == trim )
1999 break;
2000
2001 if ( trim->m_ei >= 0 )
2002 break; // not singular
2003
2004 if ( trim->m_vi[1-tvi] == old_vi )
2005 trim->m_vi[1-tvi] = new_vi;
2006 else
2007 break;
2008
2009 if ( trim->m_vi[tvi] == old_vi )
2010 trim->m_vi[tvi] = new_vi;
2011 else
2012 break;
2013 }
2014 }
2015 }
2016 return true;
2017 }
2018
SetStartPoint(ON_3dPoint start_point)2019 ON_BOOL32 ON_BrepEdge::SetStartPoint(ON_3dPoint start_point)
2020 {
2021 return false;
2022 }
2023
SetEndPoint(ON_3dPoint end_point)2024 ON_BOOL32 ON_BrepEdge::SetEndPoint(ON_3dPoint end_point)
2025 {
2026 return false;
2027 }
2028
SetStartPoint(ON_3dPoint point)2029 ON_BOOL32 ON_BrepTrim::SetStartPoint(ON_3dPoint point)
2030 {
2031 if ( 0 == m_brep )
2032 return false;
2033 if ( point.x == ON_UNSET_VALUE || point.y == ON_UNSET_VALUE )
2034 return false;
2035 if ( m_c2i < 0 || m_c2i >= m_brep->m_C2.Count() )
2036 return false;
2037 const ON_Curve* c2 = m_brep->m_C2[m_c2i];
2038 if ( 0 == c2 )
2039 return false;
2040
2041 point.z = 0.0;
2042 ON_Interval domain = Domain();
2043 ON_3dPoint q = PointAtStart();
2044 q.z = 0;
2045 if ( point != q )
2046 {
2047 /*
2048 ON_NurbsCurve* nc2 = 0;
2049 if ( ProxyCurveDomain() == c2->Domain() && !ProxyCurveIsReversed() )
2050 nc2 = ON_NurbsCurve::Cast(c2);
2051 int use_count = (0 != nc2 ) ? m_brep->TrimCurveUseCount(m_c2i,2) : 0;
2052 if ( 0 == nc2 || use_count )
2053 {
2054 nc2 = NurbsCurve();
2055 if ( 0 == nc2 )
2056 return false;
2057 }
2058 nc2->ClampEnd();
2059 nc2->SetDomain(domain[0],domain[1]);
2060 if ( nc2->GetLocalClosestPoint( point, domain[0], &t ) )
2061 {
2062 nc2->Trim( ON_Interval(t,domain[1] );
2063 }
2064 */
2065 }
2066 return false;
2067 }
2068
SetEndPoint(ON_3dPoint end_point)2069 ON_BOOL32 ON_BrepTrim::SetEndPoint(ON_3dPoint end_point)
2070 {
2071 return false;
2072 }
2073
2074
CloseTrimGap(ON_BrepTrim & trim0,ON_BrepTrim & trim1)2075 bool ON_Brep::CloseTrimGap( ON_BrepTrim& trim0, ON_BrepTrim& trim1 )
2076 {
2077
2078 // carefully close gap between end of prev_trim and start of next_trim
2079
2080 // make sure trim0 and trim1 are adjacent trims in a trimming loop
2081 if ( trim0.m_vi[1] != trim1.m_vi[0] )
2082 return false;
2083 if ( trim0.m_li != trim1.m_li )
2084 return false;
2085 if ( trim0.m_li < 0 || trim0.m_li >= m_L.Count() )
2086 return false;
2087 ON_BrepLoop& loop = m_L[trim0.m_li];
2088 int lti;
2089 if ( loop.m_ti.Count() == 1 && trim0.m_trim_index == trim1.m_trim_index )
2090 {
2091 if ( trim0.IsClosed() )
2092 return true;
2093 lti = 0;
2094 }
2095 else
2096 {
2097 for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
2098 {
2099 if ( loop.m_ti[lti] == trim0.m_trim_index && loop.m_ti[(lti+1)%loop.m_ti.Count()] == trim1.m_trim_index )
2100 break;
2101 }
2102 }
2103 if ( lti >= loop.m_ti.Count() )
2104 return false;
2105
2106 // determine where trims end and where they should meet.
2107 ON_Interval domain0 = trim0.Domain();
2108 ON_Interval domain1 = trim1.Domain();
2109 double t0 = domain0[1];
2110 double t1 = domain1[0];
2111 ON_3dPoint p0, p1;
2112 trim0.EvPoint( t0, p0 );
2113 trim1.EvPoint( t1, p1 );
2114 p0.z = 0.0;
2115 p1.z = 0.0;
2116 ON_3dPoint p = ON_Line(p0,p1).PointAt(0.5);
2117 if ( p0.x == p1.x )
2118 p.x = p0.x;
2119 if ( p0.y == p1.y )
2120 p.y = p0.y;
2121
2122 int coord0_lock = -1;
2123 //int coord1_lock = -1;
2124 switch(trim0.m_iso)
2125 {
2126 case ON_Surface::x_iso:
2127 case ON_Surface::W_iso:
2128 case ON_Surface::E_iso:
2129 // vertical iso curve - lock x coordinate
2130 coord0_lock = 0;
2131 break;
2132 case ON_Surface::y_iso:
2133 case ON_Surface::S_iso:
2134 case ON_Surface::N_iso:
2135 // horizontal iso curve - lock y coordinate
2136 coord0_lock = 1;
2137 break;
2138 default:
2139 coord0_lock = -1;
2140 }
2141
2142 switch(trim1.m_iso)
2143 {
2144 case ON_Surface::x_iso:
2145 case ON_Surface::W_iso:
2146 case ON_Surface::E_iso:
2147 // vertical iso curve - lock x coordinate
2148 // coord1_lock = 0;
2149 switch(coord0_lock)
2150 {
2151 case 0:
2152 if ( ON_Surface::x_iso == trim0.m_iso && ON_Surface::x_iso != trim1.m_iso )
2153 p.x = p1.x; // trim1 is on surface edge
2154 else if ( ON_Surface::x_iso != trim0.m_iso && ON_Surface::x_iso == trim1.m_iso )
2155 p.x = p0.x; // trim0 is on surface edge
2156 else
2157 {
2158 // longest one wins
2159 if ( p0.DistanceTo(trim0.PointAtStart()) >= p1.DistanceTo(trim1.PointAtEnd()) )
2160 p.x = p0.x;
2161 else
2162 p.x = p1.x;
2163 }
2164 break;
2165 case 1:
2166 p.x = p1.x;
2167 p.y = p0.y;
2168 break;
2169 default:
2170 p.x = p1.x;
2171 break;
2172 }
2173 break;
2174 case ON_Surface::y_iso:
2175 case ON_Surface::S_iso:
2176 case ON_Surface::N_iso:
2177 // horizontal iso curve - lock y coordinate
2178 // coord1_lock = 1;
2179 switch(coord0_lock)
2180 {
2181 case 0:
2182 p.x = p0.x;
2183 p.y = p1.y;
2184 break;
2185 case 1:
2186 if ( ON_Surface::x_iso == trim0.m_iso && ON_Surface::x_iso != trim1.m_iso )
2187 p.y = p1.y; // trim1 is on surface edge
2188 else if ( ON_Surface::x_iso != trim0.m_iso && ON_Surface::x_iso == trim1.m_iso )
2189 p.y = p0.y; // trim0 is on surface edge
2190 else
2191 {
2192 // longest one wins
2193 if ( p0.DistanceTo(trim0.PointAtStart()) >= p1.DistanceTo(trim1.PointAtEnd()) )
2194 p.y = p0.y;
2195 else
2196 p.y = p1.y;
2197 }
2198 break;
2199 default:
2200 p.x = p1.x;
2201 break;
2202 }
2203 break;
2204 default:
2205 switch(coord0_lock)
2206 {
2207 case 0:
2208 p.x = p0.x;
2209 break;
2210 case 1:
2211 p.y = p0.y;
2212 break;
2213 }
2214 break;
2215 }
2216
2217 if (ON_ComparePoint(3,0,&p.x,&p0.x))
2218 {
2219 trim0.SetEndPoint(p);
2220 }
2221 if (ON_ComparePoint(3,0,&p.x,&p1.x))
2222 {
2223 trim1.SetStartPoint(p);
2224 }
2225
2226 return true;
2227 }
2228
CollapseEdge(int edge_index,bool bCloseTrimGap,int vertex_index)2229 bool ON_Brep::CollapseEdge( int edge_index, bool bCloseTrimGap, int vertex_index )
2230 {
2231 ON_BrepEdge* edge = Edge(edge_index);
2232 if ( 0 == edge )
2233 return false;
2234 edge_index = edge->m_edge_index; // clear high bit
2235
2236 if ( -1 == vertex_index )
2237 vertex_index = edge->m_vi[0];
2238 ON_BrepVertex* vertex = Vertex(vertex_index);
2239 if ( 0 == vertex )
2240 return false;
2241 vertex_index = vertex->m_vertex_index; // clear high bit
2242
2243 int trim_count = edge->m_ti.Count();
2244 if ( trim_count > 0 )
2245 {
2246 ON_SimpleArray<int> ti(trim_count);
2247 ON_SimpleArray<int> li(trim_count);
2248 ON_SimpleArray<int> prev_ti(trim_count);
2249 ON_SimpleArray<int> next_ti(trim_count);
2250 int i, eti;
2251 for ( eti = 0; eti < trim_count; eti++ )
2252 {
2253 i = edge->m_ti[eti];
2254 if ( i < 0 || i >= m_T.Count() )
2255 continue;
2256 const ON_BrepTrim& trim = m_T[i];
2257 if ( trim.m_trim_index != i )
2258 return false;
2259 if ( trim.m_li < 0 || trim.m_li >= m_L.Count() )
2260 return false;
2261 i = PrevTrim(trim.m_trim_index);
2262 if ( i < 0 || i == trim.m_trim_index )
2263 return false;
2264 prev_ti.Append(i);
2265 i = NextTrim(trim.m_trim_index);
2266 if ( i < 0 || i == trim.m_trim_index )
2267 return false;
2268 next_ti.Append(i);
2269 ti.Append(trim.m_trim_index);
2270 li.Append(trim.m_li);
2271 }
2272
2273 ChangeVertex(edge->m_vi[0], vertex_index, true);
2274 ChangeVertex(edge->m_vi[1], vertex_index, true);
2275
2276 trim_count = ti.Count();
2277 for ( eti = 0; eti < trim_count; eti++ )
2278 {
2279 i = ti[eti];
2280 ON_BrepTrim& trim = m_T[i];
2281 //ON_BrepLoop& loop = m_L[li[eti]];
2282 ON_BrepTrim& prev_trim = m_T[prev_ti[eti]];
2283 ON_BrepTrim& next_trim = m_T[next_ti[eti]];
2284 DeleteTrim(trim,false);
2285 if ( bCloseTrimGap )
2286 CloseTrimGap(prev_trim,next_trim);
2287 }
2288 }
2289
2290 DeleteEdge(*edge,true);
2291 return true;
2292 }
2293
RemoveWireEdges(bool bDeleteVertices)2294 int ON_Brep::RemoveWireEdges( bool bDeleteVertices )
2295 {
2296 int rc = 0;
2297 int ei, count = m_E.Count();
2298 for ( ei = 0; ei < count; ei++ )
2299 {
2300 if ( ei == m_E[ei].m_edge_index && 0 == m_E[ei].m_ti.Count() )
2301 {
2302 rc++;
2303 DeleteEdge( m_E[ei], bDeleteVertices );
2304 }
2305 }
2306 return rc;
2307 }
2308
RemoveWireVertices()2309 int ON_Brep::RemoveWireVertices()
2310 {
2311 int rc = 0;
2312 int vi, count = m_V.Count();
2313 for ( vi = 0; vi < count; vi++ )
2314 {
2315 if ( vi == m_V[vi].m_vertex_index && 0 == m_V[vi].m_ei.Count() )
2316 {
2317 rc++;
2318 DeleteVertex( m_V[vi] );
2319 }
2320 }
2321 return rc;
2322 }
2323
2324
RemoveNesting(bool bExtractSingleSegments,bool bEdges,bool bTrimCurves)2325 bool ON_Brep::RemoveNesting(
2326 bool bExtractSingleSegments,
2327 bool bEdges,
2328 bool bTrimCurves
2329 )
2330 {
2331 bool rc = false;
2332 // TODO
2333 int i, count;
2334 ON_PolyCurve* polycurve;
2335
2336 if ( bEdges )
2337 {
2338 count = m_C3.Count();
2339 for ( i = 0; i < count; i++ )
2340 {
2341 polycurve = ON_PolyCurve::Cast(m_C3[i]);
2342 if ( 0 != polycurve )
2343 {
2344 if ( polycurve->RemoveNestingEx() )
2345 rc = true;
2346 if ( bExtractSingleSegments && 1 == polycurve->Count() )
2347 {
2348 // TODO - extract segment and update edge's proxy information
2349 }
2350 }
2351 }
2352 }
2353
2354 if ( bTrimCurves )
2355 {
2356 count = m_C2.Count();
2357 for ( i = 0; i < count; i++ )
2358 {
2359 polycurve = ON_PolyCurve::Cast(m_C2[i]);
2360 if ( 0 != polycurve )
2361 {
2362 if ( polycurve->RemoveNestingEx() )
2363 rc = true;
2364 if ( bExtractSingleSegments && 1 == polycurve->Count() )
2365 {
2366 // TODO - extract segment and update trims's proxy information
2367 }
2368 }
2369 }
2370 }
2371
2372 return rc;
2373 }
2374
IsSlitTrim(const ON_BrepTrim & T)2375 static bool IsSlitTrim(const ON_BrepTrim& T)
2376
2377 {
2378 int tid = T.m_trim_index;
2379 if (tid < 0)
2380 return false;
2381
2382 const ON_BrepLoop* pL = T.Loop();
2383 if (!pL)
2384 return false;
2385
2386 const ON_Brep* pB = T.Brep();
2387 if (!pB)
2388 return false;
2389
2390 const ON_BrepEdge* pE = T.Edge();
2391 if (!pE || pE->m_edge_index < 0 || pE->m_ti.Count() != 2)
2392 return false;
2393
2394 int atid = (pE->m_ti[0] == tid) ? pE->m_ti[1] : pE->m_ti[0];
2395 if (atid < 0)
2396 return false;
2397
2398 const ON_BrepTrim& AT = pB->m_T[atid];
2399 if (AT.m_trim_index < 0)
2400 return false;
2401
2402 if (AT.Loop() != pL)
2403 return false;
2404
2405 const ON_Surface* pSrf = T.SurfaceOf();
2406 if (!pSrf)
2407 return false;
2408
2409 double utol = 0.25*pSrf->Domain(0).Length();
2410 double vtol = 0.25*pSrf->Domain(1).Length();
2411
2412 bool bRev = (T.m_bRev3d == AT.m_bRev3d) ? false : true;
2413
2414 ON_2dPoint P = T.PointAtStart();
2415 ON_2dPoint AP = (bRev) ? AT.PointAtEnd() : AT.PointAtStart();
2416
2417 if (fabs(P[0] - AP[0]) > utol)
2418 return false;
2419 if (fabs(P[1] - AP[1]) > vtol)
2420 return false;
2421
2422 P = T.PointAtEnd();
2423 AP = (bRev) ? AT.PointAtStart() : AT.PointAtEnd();
2424
2425 if (fabs(P[0] - AP[0]) > utol)
2426 return false;
2427 if (fabs(P[1] - AP[1]) > vtol)
2428 return false;
2429
2430 return true;
2431 }
2432
ON_BrepRemoveSlits(ON_BrepLoop & L)2433 static bool ON_BrepRemoveSlits(ON_BrepLoop& L)
2434
2435 {
2436 if (L.m_loop_index < 0)
2437 return false;
2438 ON_BrepFace* pF = L.Face();
2439 if (!pF)
2440 return false;
2441 ON_Brep* pB = L.Brep();
2442 if (!pB)
2443 return false;
2444 //Check if anything or everything can be removed.
2445 ON_SimpleArray<bool> bIsSlit(L.m_ti.Count());
2446 ON_SimpleArray<int> slits(L.m_ti.Count());
2447 bool all_slits = true;
2448 bool some_slits = false;
2449 int tcount = L.m_ti.Count();
2450 int i;
2451 for (i=0; i<tcount; i++){
2452 ON_BrepTrim& T = pB->m_T[L.m_ti[i]];
2453 if (IsSlitTrim(T)){
2454 bIsSlit.Append(true);
2455 slits.Append(T.m_trim_index);
2456 some_slits = true;
2457 }
2458 else {
2459 bIsSlit.Append(false);
2460 all_slits = false;
2461 }
2462 }
2463
2464 if (all_slits){
2465 pB->DeleteLoop(L, true);
2466 return true;
2467 }
2468
2469 if (!some_slits)
2470 return false;
2471
2472 ON_SimpleArray<bool> bUsed = bIsSlit;
2473
2474 ON_ClassArray<ON_SimpleArray<int> > NewLoops;
2475
2476 //bool done = false;
2477 int b = 0;
2478 while (b < tcount){
2479 int start_trim = -1;
2480 for (i=0; i<tcount; i++){
2481 if (!bUsed[i]){
2482 start_trim = i;
2483 break;
2484 }
2485 }
2486 if (start_trim < 0)
2487 break;
2488 ON_SimpleArray<int>& nl = NewLoops.AppendNew();
2489 b++;
2490 nl.Append(start_trim);
2491 bUsed[start_trim] = true;
2492 int next_trim = (start_trim+1)%tcount;
2493 int c = 0;
2494 while (c < tcount){
2495 if (!bUsed[next_trim]){
2496 nl.Append(next_trim);
2497 bUsed[next_trim] = true;
2498 next_trim = (next_trim+1)%tcount;
2499 c++;
2500 continue;
2501 }
2502 if (next_trim == start_trim)
2503 break;
2504 if (bIsSlit[next_trim]){
2505 int this_trim = next_trim;
2506 ON_BrepTrim& T = pB->m_T[L.m_ti[next_trim]];
2507 ON_BrepEdge* pE = T.Edge();
2508 int atid = (pE->m_ti[0] == T.m_trim_index) ? pE->m_ti[1] : pE->m_ti[0];
2509 next_trim = -1;
2510 for (i=0; i<tcount; i++){
2511 if (L.m_ti[i] == atid){
2512 next_trim = i;
2513 break;
2514 }
2515 }
2516 if (next_trim == -1)
2517 return false;
2518 if (next_trim > this_trim)
2519 c += next_trim - this_trim;
2520 else c += tcount - this_trim + next_trim;
2521 next_trim = (next_trim+1)%tcount;
2522 c++;
2523 }
2524 }
2525 if (c >= tcount)
2526 return false;
2527 }
2528 if (b >= tcount)
2529 return false;
2530
2531 for (i=0; i<NewLoops.Count(); i++){
2532 ON_SimpleArray<int>& nl = NewLoops[i];
2533 int j;
2534 for (j=0; j<nl.Count(); j++)
2535 nl[j] = L.m_ti[nl[j]];
2536 }
2537
2538 bool bOuter = (L.m_type == ON_BrepLoop::outer) ? true : false;
2539
2540 for (i=0; i<slits.Count(); i++){
2541 ON_BrepTrim& T = pB->m_T[slits[i]];
2542 T.m_li = -1;
2543 pB->DeleteTrim(T, true);
2544 }
2545
2546 //int loop_count = pB->m_L.Count();
2547
2548 L.m_ti.SetCount(0);
2549 pB->DeleteLoop(L, true);
2550
2551 for (i=0; i<NewLoops.Count(); i++){
2552 ON_BrepLoop& nL = pB->NewLoop(ON_BrepLoop::unknown, *pF);
2553 ON_SimpleArray<int>& nl = NewLoops[i];
2554 nL.m_ti = nl;
2555 int j;
2556 for (j=0; j<nl.Count(); j++){
2557 ON_BrepTrim& T = pB->m_T[nl[j]];
2558 T.m_li = nL.m_loop_index;
2559 }
2560 nL.m_type = pB->ComputeLoopType(nL);
2561 if (bOuter && nL.m_type == ON_BrepLoop::outer){
2562 int a = pF->m_li[0];
2563 pF->m_li[0] = nL.m_loop_index;
2564 for (j=pF->m_li.Count()-1; j>0; j--){
2565 if (pF->m_li[j] == nL.m_loop_index){
2566 pF->m_li[j] = a;
2567 break;
2568 }
2569 }
2570 }
2571 pB->SetTrimBoundingBoxes(nL, true);
2572 }
2573 return true;
2574 }
2575
2576 //This removes all slit trims from F that are not joined to another face.
2577 //Unlike ON_Brep::RemoveSlits(), this will remove slit pairs from a loop in cases
2578 //that will result in the creation of more loops. Caller is responsible for calling
2579 //ON_Brep::Compact() to get rid of deleted trims and loops.
2580
ON_BrepRemoveSlits(ON_BrepFace & F)2581 bool ON_BrepRemoveSlits(ON_BrepFace& F)
2582
2583 {
2584 //For each loop, look for slit pairs that fall between non slits and
2585 //break the loop at the pair.
2586 //After all loops have been split, call ON_Brep::RemoveSlits() on the result.
2587
2588 if (F.m_face_index < 0)
2589 return false;
2590 ON_Brep* pB = F.Brep();
2591 if (!pB)
2592 return false;
2593 bool rc = false;
2594 int loop_count = F.m_li.Count();
2595 int i;
2596 for (i=0; i<loop_count; i++){
2597 ON_BrepLoop& L = pB->m_L[F.m_li[i]];
2598 if (L.m_loop_index < 0)
2599 continue;
2600 if (ON_BrepRemoveSlits(L))
2601 rc = true;
2602 }
2603 return rc;
2604 }
2605
2606
CreateNewTrimList(const ON_BrepLoop & L0,int tid0,const ON_BrepLoop & L1,int tid1,ON_SimpleArray<int> & new_tids)2607 static void CreateNewTrimList(const ON_BrepLoop& L0, int tid0,//into L0.m_ti
2608 const ON_BrepLoop& L1, int tid1,//into L1.m_ti
2609 ON_SimpleArray<int>& new_tids //into brep.m_T
2610 )
2611
2612 {
2613 new_tids.Reserve(L0.m_ti.Count() + L1.m_ti.Count() - 2);
2614
2615 int count = L0.m_ti.Count();
2616 int i;
2617 for (i=0; i<count-1; i++)
2618 new_tids.Append(L0.m_ti[(tid0+1+i)%count]);
2619
2620 count = L1.m_ti.Count();
2621 for (i=0; i<count-1; i++)
2622 new_tids.Append(L1.m_ti[(tid1+1+i)%count]);
2623
2624 return;
2625 }
2626
ON_BrepMergeFaces(ON_Brep & B,int fid0,int fid1)2627 int ON_BrepMergeFaces(ON_Brep& B, int fid0, int fid1)
2628
2629 {
2630 if (fid0 == fid1)
2631 return -1;
2632
2633 if (fid0 < 0 || fid0 >= B.m_F.Count())
2634 return -1;
2635 ON_BrepFace& F0 = B.m_F[fid0];
2636 if (F0.m_face_index < 0)
2637 return -1;
2638
2639 if (fid1 < 0 || fid1 >= B.m_F.Count())
2640 return -1;
2641 ON_BrepFace& F1 = B.m_F[fid1];
2642 if (F1.m_face_index < 0)
2643 return -1;
2644
2645 if (F0.m_si != F1.m_si)
2646 return -1;
2647
2648 //Find a manifold edge that joins the two faces and combine the loops by removing
2649 //the trims at that edge.
2650
2651 ON_BrepEdge* pE = 0;
2652
2653 int li;
2654 int tid0 = -1, tid1 = -1;
2655 for (li=0; li<F0.m_li.Count() && !pE; li++){
2656 ON_BrepLoop& L = B.m_L[F0.m_li[li]];
2657 int ti;
2658 for (ti=0; ti<L.m_ti.Count() && !pE; ti++){
2659 ON_BrepTrim& T0 = B.m_T[L.m_ti[ti]];
2660 ON_BrepEdge* pEE = T0.Edge();
2661 if (!pEE || pEE->m_ti.Count() != 2)
2662 continue;
2663 tid0 =T0.m_trim_index;
2664 tid1 = (pEE->m_ti[0] == tid0) ? pEE->m_ti[1] : pEE->m_ti[0];
2665 if (tid0 < 0 || tid1 < 0)
2666 continue;
2667 ON_BrepTrim& T1 = B.m_T[tid1];
2668 if (T1.FaceIndexOf() == fid1 && T0.m_bRev3d != T1.m_bRev3d){
2669 pE = pEE;
2670 break;
2671 }
2672 }
2673 }
2674
2675 if (!pE || tid0 < 0 || tid1 < 0)
2676 return -1;
2677
2678 ON_BrepTrim& T0 = B.m_T[tid0];
2679 ON_BrepTrim& T1 = B.m_T[tid1];
2680
2681 int lid0 = T0.m_li;
2682 if (lid0 < 0)
2683 return -1;
2684 ON_BrepLoop& L0 = B.m_L[lid0];
2685 if (L0.m_loop_index < 0)
2686 return -1;
2687 if (L0.Face() != &F0)
2688 return -1;
2689 int i;
2690 int ti0 = -1;
2691 for (i=0; i<L0.m_ti.Count(); i++){
2692 const ON_BrepTrim& T = B.m_T[L0.m_ti[i]];
2693 if (T.m_trim_index == tid0){
2694 ti0 = i;
2695 break;
2696 }
2697 }
2698 if (ti0 < 0)
2699 return -1;
2700
2701 int lid1 = T1.m_li;
2702 if (lid1 < 0)
2703 return -1;
2704 ON_BrepLoop& L1 = B.m_L[lid1];
2705 if (L1.m_loop_index < 0)
2706 return -1;
2707 if (L1.Face() != &F1)
2708 return -1;
2709 int ti1 = -1;
2710 for (i=0; i<L1.m_ti.Count(); i++){
2711 const ON_BrepTrim& T = B.m_T[L1.m_ti[i]];
2712 if (T.m_trim_index == tid1){
2713 ti1 = i;
2714 break;
2715 }
2716 }
2717 if (ti1 < 0)
2718 return -1;
2719
2720
2721 ON_SimpleArray<int> new_tids;
2722 CreateNewTrimList(L0, ti0, L1, ti1, new_tids);
2723
2724 ON_BrepLoop* pL;
2725 ON_BrepLoop* pD;
2726 ON_BrepFace* pF;
2727 ON_BrepFace* pDF;
2728 int rc;
2729 if (L1.m_type != ON_BrepLoop::inner){
2730 pL = &L0;
2731 pD = &L1;
2732 rc = fid0;
2733 pF = &F0;
2734 pDF = &F1;
2735 }
2736 else {
2737 pL = &L1;
2738 pD = &L0;
2739 rc = fid1;
2740 pF = &F1;
2741 pDF = &F0;
2742 }
2743 pL->m_ti = new_tids;
2744 pL->m_pbox.Destroy();
2745 pD->m_ti.SetCount(0);
2746 T0.m_li = -1;
2747 T1.m_li = -1;
2748 B.DeleteTrim(T0, true);
2749 B.DeleteTrim(T1, true);
2750 B.DeleteLoop(*pD, true);
2751 for (i=0; i<pL->m_ti.Count(); i++)
2752 B.m_T[pL->m_ti[i]].m_li = pL->m_loop_index;
2753 for (i=0; i<pDF->m_li.Count(); i++){
2754 ON_BrepLoop& ML = B.m_L[pDF->m_li[i]];
2755 ML.m_fi = rc;
2756 pF->m_li.Append(ML.m_loop_index);
2757 }
2758 pDF->m_li.SetCount(0);
2759 B.DeleteFace(*pDF, true);
2760 ON_BrepRemoveSlits(B.m_F[rc]);
2761
2762 B.SetTrimBoundingBoxes(B.m_F[rc], true);
2763
2764 return rc;
2765
2766 }
2767
2768 typedef int srf_face[2];
2769
sfsort(const srf_face * a,const srf_face * b)2770 static int sfsort(const srf_face* a, const srf_face* b)
2771 {
2772 if ((*a)[0] < (*b)[0])
2773 return -1;
2774 if ((*b)[0] < (*a)[0])
2775 return 1;
2776 return 0;
2777 }
2778
ON_BrepMergeFaces(ON_Brep & B)2779 bool ON_BrepMergeFaces(ON_Brep& B)
2780
2781 {
2782 bool rc = false;
2783 ON_SimpleArray<srf_face> SF(B.m_F.Count());
2784 int i;
2785 for (i=0; i<B.m_F.Count(); i++){
2786 const ON_BrepFace& F = B.m_F[i];
2787 if (F.m_face_index < 0)
2788 continue;
2789 if (F.m_si < 0)
2790 continue;
2791 srf_face& sf = SF.AppendNew();
2792 sf[0] = F.m_si;
2793 sf[1] = i;
2794 }
2795 if (SF.Count() < 2)
2796 return false;
2797 SF.QuickSort(sfsort);
2798 //int si = SF[0][0];
2799 int start_i = 0;
2800 while (start_i<SF.Count()){
2801 int next_i = start_i+1;
2802 while (next_i<SF.Count() && SF[next_i][0] == SF[start_i][0])
2803 next_i++;
2804 if (next_i == start_i+1){
2805 start_i++;
2806 continue;
2807 }
2808 for (i=start_i; i<next_i-1; i++){
2809 int j;
2810 for (j=i+1; j<next_i; j++){
2811 int new_id = ON_BrepMergeFaces(B, SF[i][1], SF[j][1]);
2812 if (new_id < 0)
2813 continue;
2814 SF[j][1] = new_id;
2815 rc = true;
2816 break;
2817 }
2818 }
2819 start_i = next_i;
2820 }
2821
2822 ON_BrepMergeAllEdges(B);
2823 return rc;
2824 }
2825
2826
MergeAdjacentEdge(ON_Brep & B,int eid)2827 static int MergeAdjacentEdge(ON_Brep& B, int eid)
2828
2829 {
2830 ON_BrepEdge& E = B.m_E[eid];
2831 if (!E.IsValid())
2832 return -1;
2833
2834 /*
2835 if (E.m_edge_user_i >= 0)
2836 return -1;
2837 */
2838
2839 if (E.m_ti.Count() == 0)
2840 return -1;
2841
2842 int i;
2843 for (i=0; i<2; i++){
2844 int neid = B.NextEdge(eid, i);
2845 if (neid >= 0){
2846 ON_BrepEdge* pE = B.CombineContiguousEdges(eid, neid);
2847 if (pE)
2848 return pE->m_edge_index;
2849 }
2850 }
2851
2852 return -1;
2853 }
2854
2855 //Merges all possible edges
ON_BrepMergeAllEdges(ON_Brep & B)2856 void ON_BrepMergeAllEdges(ON_Brep& B)
2857
2858 {
2859 int i;
2860 int count = B.m_E.Count();
2861 for (i=0; i<count; i++){
2862 int eid = i;
2863 int j = 0;
2864 while (eid >= 0 && j < count){
2865 eid = MergeAdjacentEdge(B, eid);
2866 j++;
2867 }
2868 }
2869 return;
2870 }
2871
2872