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