opennurbs_brep_tools.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00017 
00018 
00019 static
00020 const ON_BrepEdge* FindLinearEdge( const ON_Brep& brep, int vi0, int vi1 )
00021 {
00022   // searchs for a linear edge connecting the vertices
00023   // brep.m_V[vi0] and brep.m_V[vi1].
00024   if ( vi0 < 0 || vi0 >= brep.m_V.Count() )
00025     return NULL;
00026   if ( vi1 < 0 || vi1 >= brep.m_V.Count() )
00027     return NULL;
00028   if ( vi0 == vi1 )
00029     return NULL;
00030   const ON_BrepVertex& v0 = brep.m_V[vi0];
00031   //const ON_BrepVertex& v1 = brep.m_V[vi1];
00032   int vei;
00033   for ( vei = 0; vei < v0.m_ei.Count(); vei++ )
00034   {
00035     const ON_BrepEdge* edge = brep.Edge( v0.m_ei[vei] );
00036     if ( !edge )
00037       continue;
00038     if ( edge->m_vi[0] != vi0 && edge->m_vi[1] != vi0 )
00039       continue;
00040     if ( edge->m_vi[0] != vi1 && edge->m_vi[1] != vi1 )
00041       continue;
00042     if ( !edge->IsLinear() )
00043       continue;
00044     return edge;
00045   }
00046   return NULL;
00047 }
00048 
00049 static
00050 void SynchFaceOrientation( ON_Brep& brep, int fi )
00051 {
00052   const ON_BrepFace* face = brep.Face(fi);
00053   if ( face )
00054   {
00055     int flip = -1, fli, lti;
00056     for ( fli = 0; fli < face->m_li.Count(); fli++ )
00057     {
00058       const ON_BrepLoop* loop = brep.Loop( face->m_li[fli] );
00059       if ( !loop )
00060         continue;
00061       for ( lti = 0; lti < loop->m_ti.Count(); lti++ )
00062       {
00063         const ON_BrepTrim* trim = brep.Trim( loop->m_ti[lti] );
00064         if ( !trim )
00065           continue;
00066         const ON_BrepEdge* edge = brep.Edge( trim->m_ei );
00067         if ( !edge )
00068           continue;
00069         if ( edge->m_ti.Count() != 2 )
00070           continue;
00071         const ON_BrepTrim* trim0 = brep.Trim( edge->m_ti[0] );
00072         const ON_BrepTrim* trim1 = brep.Trim( edge->m_ti[1] );
00073         if ( !trim0 || !trim1 )
00074           continue;
00075         bool bRev0 = trim0->m_bRev3d ? true : false;
00076         bool bRev1 = trim1->m_bRev3d ? true : false;
00077         if ( bRev0 == bRev1 )
00078         {
00079           if ( flip == -1 )
00080             flip = 1;
00081           else if (flip != 1 )
00082             return;
00083         }
00084         else
00085         {
00086           if ( flip == -1 )
00087             flip = 0;
00088           else if (flip != 0 )
00089             return;
00090         }
00091       }
00092     }
00093     if ( flip == 1 )
00094       brep.FlipFace(brep.m_F[fi]);
00095   }
00096 }
00097 
00098 ON_BrepFace* ON_Brep::NewRuledFace(
00099       const ON_BrepEdge& edgeA,
00100       bool bRevEdgeA,
00101       const ON_BrepEdge& edgeB, 
00102       bool bRevEdgeB
00103       )
00104 {
00105   if ( edgeA.m_edge_index == edgeB.m_edge_index )
00106     return NULL;
00107   if ( Edge( edgeA.m_edge_index) != &edgeA )
00108     return NULL;
00109   if ( Edge( edgeB.m_edge_index) != &edgeB )
00110     return NULL;
00111 
00112   ON_NurbsCurve cA, cB;
00113   if ( !edgeA.GetNurbForm( cA ) )
00114     return NULL;
00115   if ( bRevEdgeA )
00116     cA.Reverse();
00117   if ( !edgeB.GetNurbForm( cB ) )
00118     return NULL;
00119   if ( bRevEdgeB )
00120     cB.Reverse();
00121   ON_NurbsSurface* srf = ON_NurbsSurface::New();
00122   if ( !srf->CreateRuledSurface( cA, cB ) )
00123   {
00124     delete srf;
00125     return NULL;
00126   }
00127 
00128   // corner vertices (sw,se,ne,nw)
00129   int vid[4] = {-1,-1,-1,-1};
00130   vid[0] = edgeA.m_vi[bRevEdgeA?1:0];
00131   vid[1] = edgeA.m_vi[bRevEdgeA?0:1];
00132   vid[2] = edgeB.m_vi[bRevEdgeB?0:1];
00133   vid[3] = edgeB.m_vi[bRevEdgeB?1:0];
00134 
00135   if ( vid[1] == vid[2] )
00136   {
00137     // make sure surface has a singular east side
00138     srf->CollapseSide( 1 );
00139   }
00140 
00141   if ( vid[1] == vid[2] )
00142   {
00143     // make sure surface has a singular west side
00144     srf->CollapseSide( 3 );
00145   }
00146 
00147   // side edges (s,e,n,w)
00148   int eid[4] = {-1,-1,-1,-1};
00149   ON_BOOL32 bRev3d[4] = {false,false,false,false};
00150   
00151   // south side
00152   eid[0] = edgeA.m_edge_index;
00153   bRev3d[0] = bRevEdgeA;
00154   
00155   // east side
00156   const ON_BrepEdge* east_edge = FindLinearEdge( *this, vid[1], vid[2] );
00157   if ( east_edge )
00158   {
00159     eid[1] = east_edge->m_edge_index;
00160     bRev3d[1] = (east_edge->m_vi[0] == vid[2]);
00161   }
00162 
00163   // north side
00164   eid[2] = edgeB.m_edge_index;
00165   bRev3d[2] = !bRevEdgeB;
00166 
00167   // west side
00168   const ON_BrepEdge* west_edge = FindLinearEdge( *this, vid[3], vid[0] );
00169   if ( west_edge )
00170   {
00171     eid[3] = west_edge->m_edge_index;
00172     bRev3d[3] = (west_edge->m_vi[0] == vid[0]);
00173   }
00174 
00175   ON_BrepFace* face = NewFace( srf, vid, eid, bRev3d );
00176   if ( face )
00177     SynchFaceOrientation( *this, face->m_face_index );
00178   return face;
00179 }
00180 
00181 
00182 ON_BrepFace* ON_Brep::NewConeFace(
00183       const ON_BrepVertex& vertex,
00184       const ON_BrepEdge& edge,
00185       bool bRevEdge
00186       )
00187 {
00188   if ( Edge( edge.m_edge_index) != &edge )
00189     return NULL;
00190   if ( Vertex( vertex.m_vertex_index) != &vertex )
00191     return NULL;
00192   if ( edge.m_vi[0] == vertex.m_vertex_index )
00193     return NULL;
00194   if ( edge.m_vi[1] == vertex.m_vertex_index )
00195     return NULL;
00196   ON_NurbsCurve c;
00197   if ( !edge.GetNurbForm( c ) )
00198     return NULL;
00199   if ( bRevEdge )
00200     c.Reverse();
00201   ON_NurbsSurface* srf = ON_NurbsSurface::New();
00202   if ( !srf->CreateConeSurface( vertex.point, c ) )
00203   {
00204     delete srf;
00205     return NULL;
00206   }
00207 
00208   // corner vertices (sw,se,ne,nw)
00209   int vid[4] = {-1,-1,-1,-1};
00210   vid[0] = edge.m_vi[bRevEdge?1:0];
00211   vid[1] = edge.m_vi[bRevEdge?0:1];
00212   vid[2] = vertex.m_vertex_index;
00213   vid[3] = vertex.m_vertex_index;
00214 
00215   // side edges (s,e,n,w)
00216   int eid[4] = {-1,-1,-1,-1};
00217   ON_BOOL32 bRev3d[4] = {false,false,false,false};
00218   
00219   // south side
00220   eid[0] = edge.m_edge_index;
00221   bRev3d[0] = bRevEdge;
00222   
00223   // east side
00224   const ON_BrepEdge* east_edge = FindLinearEdge( *this, vid[1], vid[2] );
00225   if ( east_edge )
00226   {
00227     eid[1] = east_edge->m_edge_index;
00228     bRev3d[1] = (east_edge->m_vi[0] == vid[2]);
00229   }
00230 
00231   // west side
00232   const ON_BrepEdge* west_edge = FindLinearEdge( *this, vid[3], vid[0] );
00233   if ( west_edge )
00234   {
00235     eid[3] = west_edge->m_edge_index;
00236     bRev3d[3] = (west_edge->m_vi[0] == vid[0]);
00237   }
00238 
00239   ON_BrepFace* face = NewFace( srf, vid, eid, bRev3d );
00240   if ( face )
00241     SynchFaceOrientation( *this, face->m_face_index );
00242   return face;
00243 }
00244 
00245 
00246 bool ON_BrepFace::SetMesh( ON::mesh_type mt, ON_Mesh* mesh )
00247 {
00248   // TODO move next to ON_BrepFace::Mesh() when opennurbs_brep.cpp is available
00249   bool rc = true;
00250   switch ( mt )
00251   {
00252   case ON::render_mesh:
00253     if ( m_render_mesh )
00254       delete m_render_mesh;
00255     m_render_mesh = mesh;
00256     break;
00257 
00258   case ON::analysis_mesh:
00259     if ( m_analysis_mesh )
00260       delete m_analysis_mesh;
00261     m_analysis_mesh = mesh;
00262     break;
00263 
00264   case ON::preview_mesh:
00265     if ( m_preview_mesh )
00266       delete m_preview_mesh;
00267     m_preview_mesh = mesh;
00268     break;
00269 
00270   default:
00271     rc = false;
00272   }
00273 
00274   return rc;
00275 }
00276 
00277 
00278 bool ON_Brep::SetTrimBoundingBoxes( ON_BOOL32 bLazy )
00279 {
00280   bool rc = true;
00281   int fi, face_count = m_F.Count();
00282   for ( fi = 0; fi < face_count; fi++ )
00283   {
00284     if ( !SetTrimBoundingBoxes( m_F[fi], bLazy ) )
00285       rc = false;
00286   }
00287   return rc;
00288 }
00289 
00290 bool ON_Brep::SetTrimBoundingBoxes( ON_BrepFace& face, ON_BOOL32 bLazy )
00291 {
00292   bool rc = true;
00293   int li, fli, loop_count = m_L.Count(), fl_count = face.m_li.Count();;
00294   for ( fli = 0; fli < fl_count; fli++ )
00295   {
00296     li = face.m_li[fli];
00297     if ( li >= 0 && li < loop_count )
00298     {
00299       if ( !SetTrimBoundingBoxes( m_L[li], bLazy ) )
00300         rc = false;
00301     }
00302   }
00303   return rc;
00304 }
00305 
00306 bool ON_Brep::SetTrimBoundingBoxes( ON_BrepLoop& loop, ON_BOOL32 bLazy )
00307 {
00308   // TL_Brep overrides this function and computes much tighter
00309   // bounding boxes that take trim.m_t[] into account.
00310   ON_BOOL32 rc = true;
00311   int ti, lti, trim_count = m_T.Count(), lt_count = loop.m_ti.Count();
00312   ON_BOOL32 bSetLoopBox = true;
00313   if ( bLazy && loop.m_pbox.IsValid() )
00314     bSetLoopBox = false;
00315   else
00316     loop.m_pbox.Destroy();
00317   for ( lti = 0; lti < lt_count; lti++ )
00318   {
00319     ti = loop.m_ti[lti];
00320     if ( ti >= 0 && ti < trim_count )
00321     {
00322       if ( !SetTrimBoundingBox( m_T[ti], bLazy ) )
00323         rc = false;
00324       else if ( bSetLoopBox )
00325         loop.m_pbox.Union( m_T[ti].m_pbox );
00326     }
00327   }
00328   return (rc && loop.m_pbox.IsValid()) ? true : false;
00329 }
00330 
00331 bool ON_Brep::SetTrimBoundingBox( ON_BrepTrim& trim, ON_BOOL32 bLazy )
00332 {
00333   // TL_Brep overrides this function and computes much 
00334   // tighter bounding boxes that take trim.m_t[] into account.
00335   ON_BOOL32 rc = true;
00336   if ( !trim.m_pbox.IsValid() || !bLazy )
00337   {
00338     trim.m_pbox.Destroy();
00339     if ( trim.ProxyCurve() )
00340     {
00341       trim.m_pbox = trim.BoundingBox();
00342       trim.m_pbox.m_min.z = 0.0;
00343       trim.m_pbox.m_max.z = 0.0;
00344     }
00345   }
00346   return (rc && trim.m_pbox.IsValid()) ? true : false;
00347 }
00348 
00349 void ON_Brep::SetTolerancesBoxesAndFlags(
00350      ON_BOOL32 bLazy,
00351      ON_BOOL32 bSetVertexTolerances,
00352      ON_BOOL32 bSetEdgeTolerances,
00353      ON_BOOL32 bSetTrimTolerances,
00354      ON_BOOL32 bSetTrimIsoFlags,
00355      ON_BOOL32 bSetTrimTypeFlags,
00356      ON_BOOL32 bSetLoopTypeFlags,
00357      ON_BOOL32 bSetTrimBoxes
00358      )
00359 {
00360   int ei, ti, li;
00361   const int trim_count = m_T.Count();
00362   const int loop_count = m_L.Count();
00363   const int edge_count = m_E.Count();
00364   if ( bSetVertexTolerances )
00365     SetVertexTolerances(bLazy);
00366   if ( bSetEdgeTolerances )
00367   {
00368     for ( ei = 0; ei < edge_count; ei++ )
00369       SetEdgeTolerance(m_E[ei],bLazy);
00370   }
00371   if ( bSetTrimTolerances )
00372   {
00373     for ( ti = 0; ti < trim_count; ti++ )
00374       SetTrimTolerance(m_T[ti],bLazy);
00375   }
00376   if ( bSetTrimIsoFlags )
00377     SetTrimIsoFlags();
00378   if ( bSetTrimTypeFlags )
00379     SetTrimTypeFlags(bLazy);
00380   if ( bSetTrimTypeFlags )
00381     SetTrimTypeFlags(bLazy);
00382   if ( bSetLoopTypeFlags )
00383   {
00384     for ( li = 0; li < loop_count; li++ )
00385     {
00386       ON_BrepLoop& loop = m_L[li];
00387       if ( loop.m_type == ON_BrepLoop::unknown || !bLazy )
00388       {
00389         loop.m_type = ComputeLoopType( loop );
00390       }
00391     }
00392   }
00393   if ( bSetTrimBoxes )
00394     SetTrimBoundingBoxes(bLazy);
00395 }
00396 
00397 static
00398 bool CheckForMatchingVertexIndices( int i, int j, int corner_vi[4] )
00399 {
00400   ON_BOOL32 rc = false;
00401   if ( corner_vi[i] >= 0 || corner_vi[j] >= 0 )
00402   {
00403     if ( corner_vi[i] == -1 )
00404     {
00405       corner_vi[i] = corner_vi[j];
00406       rc = true;
00407     }
00408     else if ( corner_vi[j] == -1 )
00409     {
00410       corner_vi[j] = corner_vi[i];
00411       rc = true;
00412     }
00413     else if ( corner_vi[i] == corner_vi[j] )
00414     {
00415       rc = true;
00416     }
00417   }
00418   return true;
00419 }
00420 
00421 
00422 ON_BrepFace* ON_Brep::NewFace(
00423        ON_Surface* pSurface,
00424        int vid[4],
00425        int eid[4],
00426        ON_BOOL32 bRev3d[4]
00427        )
00428 {
00429   m_bbox.Destroy();
00430   m_is_solid = 0;
00431   ON_BOOL32 bAddedSurface = false;
00432   ON_BrepFace* pFace = NULL;
00433   if ( !pSurface )
00434     return NULL;
00435   int si;
00436   for ( si = 0; si < m_S.Count(); si++ )
00437   {
00438     if ( pSurface == m_S[si] )
00439       break;
00440   }
00441   if ( si >= m_S.Count() )
00442   {
00443     si = AddSurface(pSurface);
00444     bAddedSurface = (si >= 0);
00445   }
00446   int face_index = NewFace(si).m_face_index;
00447   if ( NewOuterLoop( face_index, vid, eid, bRev3d ) )
00448   {
00449     pFace = &m_F[face_index];
00450   }
00451   else 
00452   {
00453     // failed
00454     if ( bAddedSurface )
00455     {
00456       m_S[si] = 0;
00457       if ( m_S.Count() == si+1 )
00458         m_S.SetCount(si);
00459     }
00460     DeleteFace( m_F[face_index], false );
00461     if ( m_F.Count() == face_index+1 )
00462     {
00463       m_F.SetCount(face_index);
00464     }
00465   }
00466   return pFace;
00467 }
00468 
00469 
00470 ON_BrepLoop* ON_Brep::NewOuterLoop(
00471        int face_index,
00472        int vid[4],
00473        int eid[4],
00474        ON_BOOL32 bRev3d[4]
00475        )
00476 {
00477   m_is_solid = 0;
00478   if ( face_index < 0 || face_index >= m_F.Count() )
00479     return NULL;
00480   ON_BrepFace& face = m_F[face_index];
00481   const ON_Surface* pSurface = face.SurfaceOf();
00482   if (!pSurface) 
00483     return NULL;
00484 
00485   double u[2], v[2];
00486   if (!pSurface->GetDomain(0, &u[0], &u[1])) 
00487       return 0;
00488   if (!pSurface->GetDomain(1, &v[0], &v[1])) 
00489       return 0;
00490 
00491   ON_3dPoint srf_P[2][2];
00492   if ( !pSurface->EvPoint(u[0],v[0],srf_P[0][0] ) )
00493     return 0;
00494   if ( !pSurface->EvPoint(u[1],v[0],srf_P[1][0] ) )
00495     return 0;
00496   if ( !pSurface->EvPoint(u[0],v[1],srf_P[0][1] ) )
00497     return 0;
00498   if ( !pSurface->EvPoint(u[1],v[1],srf_P[1][1] ) )
00499     return 0;
00500 
00501 
00502   ON_BOOL32 bIsSingular[4]; // south, east, north, west
00503   ON_BOOL32 bIsClosed[2]; // u direction, v direction
00504   int i, eti;
00505   ON_Curve* c3[4] = {NULL,NULL,NULL,NULL};
00506 
00507   for ( i = 0; i < 4; i++ )
00508   {
00509     if ( bRev3d[i] )
00510       bRev3d[i] = 1; // do this so we can use 1-bRev3d[i] as an array index
00511   }
00512 
00513   // check specified edge indices
00514   for ( i = 0; i < 4; i++ )
00515   {
00516     if ( eid[i] != -1 )
00517     {
00518       if ( eid[i] < 0 || eid[i] >= m_E.Count() )
00519       {
00520         ON_ERROR("Bad edge index passed to ON_BrepNewFace.");
00521         return 0;
00522       }
00523       const int* edge_vi = m_E[eid[i]].m_vi;
00524       int vi0 = edge_vi[bRev3d[i]];
00525       int vi1 = edge_vi[1-bRev3d[i]];
00526       if ( vi0 < 0 || vi1 < 0 )
00527       {
00528         ON_ERROR("ON_Brep::NewFace(ON_Surface*,...) error: Bad edge vertex informtion.");
00529         return 0;
00530       }
00531       if ( vid[i] == -1 )
00532         vid[i] = vi0;
00533       else if ( vid[i] != vi0 )
00534       {
00535         ON_ERROR("ON_Brep::NewFace(ON_Surface*,...) error: Edge and vertex informtion do not match.");
00536         return 0;
00537       }
00538       if ( vid[(i+1)%4] == -1 )
00539         vid[(i+1)%4] = vi1;
00540       else if ( vid[(i+1)%4] != vi1 )
00541       {
00542         ON_ERROR("ON_Brep::NewFace(ON_Surface*,...) error: Edge and vertex informtion do not match.");
00543         return 0;
00544       }
00545     }
00546   }
00547 
00548   // check specified vertex indices
00549   for ( i = 0; i < 4; i++ )
00550   {
00551     if ( vid[i] != -1 )
00552     {
00553       if ( vid[i] < 0 || vid[i] >= m_V.Count() )
00554       {
00555         ON_ERROR("Bad vertex index passed to ON_Brep::NewFace.");
00556         return 0;
00557       }
00558     }
00559   }
00560 
00561   for ( i = 0; i < 4; i++ )
00562     bIsSingular[i] = pSurface->IsSingular(i);
00563   for ( i = 0; i < 2; i++ )
00564     bIsClosed[i] = pSurface->IsClosed(i);
00565 
00566   for (i = 0; i < 2; i++ )
00567   {
00568     if ( bIsClosed[i] )
00569     {
00570       int j = i?0:1;
00571       int k = j+2;
00572       if ( eid[j] == -1 && eid[k] != -1)
00573       {
00574         eid[j] = eid[k];
00575         bRev3d[j] = 1-bRev3d[k];
00576       }
00577       else if ( eid[k] == -1 && eid[j] != -1)
00578       {
00579         eid[k] = eid[j];
00580         bRev3d[k] = 1-bRev3d[j];
00581       }
00582       else if ( eid[k] != -1 || eid[j] != -1)
00583       {
00584         if ( eid[j] != eid[k] || bRev3d[j] != 1-bRev3d[k] )
00585         {
00586           ON_ERROR("Bad edge information passed to ON_Brep::NewFace.");
00587           return 0;
00588         }
00589       }
00590     }
00591   }  
00592 
00593   // if surface has singularities or is closed, make sure vertex and edge information is correct
00594   for ( i = 0; i < 4; i++ )
00595   {
00596     if ( bIsSingular[i] )
00597     {
00598       if ( eid[i] != -1 || bRev3d[i] )
00599       {
00600         ON_ERROR("Bad edge information passed to ON_Brep::NewFace.");
00601         return 0;
00602       }
00603     }
00604     if ( bIsSingular[i] || bIsClosed[i%2] )
00605     {
00606       if ( !CheckForMatchingVertexIndices(i,(i+1)%4,vid) )
00607       {
00608         ON_ERROR("Bad vertex indices passed to ON_Brep::NewFace.");
00609         return 0;
00610       }
00611     }
00612   }
00613 
00614   m_C3.Reserve( m_C3.Count() + 4 );
00615   // create missing 3d curves
00616   bool bEdgeIsClosed[4]; // true if 3d edge is closed or edge is singular.
00617   for ( i = 0; i < 4; i++ )
00618   {
00619     bEdgeIsClosed[i] = false;
00620     if ( eid[i] != -1 )
00621     {
00622       const ON_BrepEdge& edge = m_E[eid[i]];
00623       bEdgeIsClosed[i] = (edge.m_vi[0] == edge.m_vi[1]);
00624       continue;
00625     }
00626     if ( bIsSingular[i] )
00627     {
00628       bEdgeIsClosed[i] = true;
00629       continue;
00630     }
00631     if ( i >= 2 && bIsClosed[(i==2)?1:0] )
00632     {
00633       bEdgeIsClosed[i] = bEdgeIsClosed[i-2];
00634       continue;
00635     }
00636     switch(i)
00637     {
00638     case 0:  // south side
00639       c3[i] = pSurface->IsoCurve(i%2, v[0]); 
00640       break;
00641     case 1:  // east side
00642       c3[i] = pSurface->IsoCurve(i%2, u[1]); 
00643       break;
00644     case 2:  // north side
00645       c3[i] = pSurface->IsoCurve(i%2, v[1]); 
00646       break;
00647     case 3:  // west side
00648       c3[i] = pSurface->IsoCurve(i%2, u[0]); 
00649       break;
00650     }
00651     if ( !c3[i] )
00652     {
00653      ON_ERROR("ON_Brep::NewLoop unable to make 3d edge curve.");
00654       return 0;
00655     }
00656     if ( pSurface->IsClosed(i%2) )
00657       bEdgeIsClosed[i] = true;
00658     else
00659       bEdgeIsClosed[i] = c3[i]->IsClosed()?true:false;
00660     if ( (i <= 1 && bRev3d[i]) || (i >= 2 && !bRev3d[i]) )
00661     {
00662       c3[i]->Reverse();
00663     }
00664   }
00665 
00666   if ( m_V.Capacity() < 2 )
00667     m_V.Reserve(4);
00668 
00669   // create missing vertices
00670   if ( vid[0] == -1 )
00671   {
00672     if ( vid[1] >= 0 && bEdgeIsClosed[0] )
00673       vid[0] = vid[1];
00674     else if ( vid[3] >= 0 && bEdgeIsClosed[3] )
00675       vid[0] = vid[3];
00676     else
00677       vid[0] = NewVertex( srf_P[0][0],0.0).m_vertex_index;
00678   }
00679 
00680   if ( vid[1] == -1 )
00681   {
00682     if ( bEdgeIsClosed[0] ) 
00683       vid[1] = vid[0];
00684     else if ( vid[2] >= 0 && bEdgeIsClosed[1] ) 
00685       vid[1] = vid[2];
00686     else
00687       vid[1] = NewVertex(srf_P[1][0],0.0).m_vertex_index;
00688   }
00689 
00690   if ( vid[2] == -1 )
00691   {
00692     if ( bEdgeIsClosed[1] ) 
00693       vid[2] = vid[1];
00694     else if (vid[3] >= 0 && bEdgeIsClosed[2] ) 
00695       vid[2] = vid[3];
00696     else
00697       vid[2] = NewVertex( srf_P[1][1],0.0).m_vertex_index;
00698   }
00699 
00700   if ( vid[3] == -1 )
00701   {
00702     if ( bEdgeIsClosed[2] ) 
00703       vid[3] = vid[2];
00704     else if ( bEdgeIsClosed[3] ) 
00705       vid[3] = vid[0];
00706     else
00707       vid[3] = NewVertex( srf_P[0][1],0.0).m_vertex_index;
00708   }
00709 
00710   if ( m_E.Capacity() < 4 )
00711     m_E.Reserve(4);
00712 
00713   // create missing edges
00714   for ( i = 0; i < 4; i++ )
00715   {
00716     if ( c3[i] )
00717     {
00718       int i0, i1;
00719       if ( bRev3d[i] )
00720       {
00721         i0 = (i+1)%4;
00722         i1 = i;
00723       }
00724       else
00725       {
00726         i0 = i;
00727         i1 = (i+1)%4;
00728       }
00729       ON_BrepEdge& edge = NewEdge( m_V[vid[i0]], m_V[vid[i1]], AddEdgeCurve( c3[i] ) );
00730       edge.m_tolerance = 0.0;
00731       eid[i] = edge.m_edge_index;
00732       if ( i == 0 && bIsClosed[1] )
00733       {
00734         eid[2] = eid[0];
00735         bRev3d[2] = 1-bRev3d[0];
00736       }
00737       else if ( i == 1 && bIsClosed[0] )
00738       {
00739         eid[3] = eid[1];
00740         bRev3d[3] = 1-bRev3d[1];
00741       }
00742     }
00743   }
00744 
00745   m_T.Reserve( m_T.Count() + 4 );
00746   m_C2.Reserve( m_C2.Count() + 4 );
00747 
00748   ON_BrepLoop& loop = NewLoop( ON_BrepLoop::outer, face );
00749 
00750   loop.m_pbox.m_min.x = u[0];
00751   loop.m_pbox.m_min.y = v[0];
00752   loop.m_pbox.m_min.z = 0.0;
00753 
00754   loop.m_pbox.m_max.x = u[1];
00755   loop.m_pbox.m_max.y = v[1];
00756   loop.m_pbox.m_max.z = 0.0;
00757 
00758   ON_3dPoint corners[4];
00759   corners[0].Set(u[0],v[0],0.0);
00760   corners[1].Set(u[1],v[0],0.0);
00761   corners[2].Set(u[1],v[1],0.0);
00762   corners[3].Set(u[0],v[1],0.0);
00763 
00764   ON_Surface::ISO srf_iso[4] = {ON_Surface::S_iso,ON_Surface::E_iso,ON_Surface::N_iso,ON_Surface::W_iso};
00765 
00766   for ( i = 0; i < 4; i++ )
00767   {
00768     ON_NurbsCurve* c2 = new ON_NurbsCurve( 2, 0, 2, 2 );
00769     c2->SetCV(0,corners[i]);
00770     c2->SetCV(1,corners[(i+1)%4]);
00771     c2->m_knot[0] = 0.0;
00772     c2->m_knot[1] = 1.0;
00773     if ( i%2 )
00774       c2->SetDomain(v[0],v[1]);
00775     else
00776       c2->SetDomain(u[0],u[1]);
00777     int c2i = AddTrimCurve( c2 );
00778     if ( bIsSingular[i] )
00779       NewSingularTrim( m_V[vid[i]],loop,srf_iso[i],c2i);
00780     else
00781     {
00782       ON_BrepTrim& trim = NewTrim( m_E[eid[i]], bRev3d[i], loop, c2i);
00783       trim.m_iso = srf_iso[i];
00784       if ( bIsClosed[(i+1)%2] ) 
00785         trim.m_type = ON_BrepTrim::seam;
00786       else {
00787         trim.m_type = ON_BrepTrim::boundary;
00788         const ON_BrepEdge& edge = m_E[eid[i]];
00789         if ( edge.m_ti.Count() > 1 )
00790         {
00791           for ( eti = 0; eti < edge.m_ti.Count(); eti++ )
00792           {
00793             m_T[edge.m_ti[eti]].m_type = ON_BrepTrim::mated;
00794           }
00795         }
00796       }
00797       trim.m_tolerance[0] = 0.0;
00798       trim.m_tolerance[1] = 0.0;
00799       trim.m__legacy_2d_tol = 0.0;
00800       trim.m__legacy_3d_tol = 0.0;
00801       trim.m__legacy_flags_Set(-1,1);
00802     }
00803   }
00804 
00805   return &m_L[loop.m_loop_index];
00806 }
00807 
00808 
00809 
00810 
00811 ON_Brep* ON_BrepBox( const ON_3dPoint* box_corners, ON_Brep* pBrep )
00812 {
00813   ON_Brep* brep = 0;
00814   int vi, ei, fi, si, c2i;
00815   if (box_corners)
00816   {
00817     if ( pBrep ) {
00818       pBrep->Destroy();
00819       brep = pBrep;
00820     }
00821     else
00822       brep = new ON_Brep();
00823     brep->m_C2.Reserve(24);
00824     brep->m_C3.Reserve(12);
00825     brep->m_S.Reserve(6);
00826     brep->m_V.Reserve(8);
00827     brep->m_E.Reserve(12);
00828     brep->m_L.Reserve(6);
00829     brep->m_T.Reserve(24);
00830     brep->m_F.Reserve(6);
00831     for ( vi = 0; vi < 8; vi++ )
00832     {
00833       brep->NewVertex( box_corners[vi], 0.0 );
00834     }
00835     for ( ei = 0; ei < 4; ei++ )
00836     {
00837       ON_BrepVertex& v0 = brep->m_V[ei];
00838       ON_BrepVertex& v1 = brep->m_V[(ei+1)%4];
00839       brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
00840       brep->NewEdge( v0, v1, ei, NULL, 0.0 );
00841     }
00842     for ( ei = 4; ei < 8; ei++ )
00843     {
00844       ON_BrepVertex& v0 = brep->m_V[ei];
00845       ON_BrepVertex& v1 = brep->m_V[ei==7?4:(ei+1)];
00846       brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
00847       brep->NewEdge( v0, v1, ei, NULL, 0.0 );
00848     }
00849     for ( ei = 8; ei < 12; ei++ )
00850     {
00851       ON_BrepVertex& v0 = brep->m_V[ei-8];
00852       ON_BrepVertex& v1 = brep->m_V[ei-4];
00853       brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
00854       brep->NewEdge( v0, v1, ei, NULL, 0.0 );
00855     }
00856 
00857     /*
00858     //           v7_______e6_____v6
00859     //            |\             |\
00860     //            | e7           | e5
00861     //            |  \ ______e4_____\ 
00862     //           e11  v4         |   v5
00863     //            |   |        e10   |
00864     //            |   |          |   |
00865     //            3---|---e2-----2   e9
00866     //            \   e8         \   |
00867     //             e3 |           e1 |
00868     //              \ |            \ |
00869     //               \v0_____e0_____\v1
00870     */
00871 
00872     struct {
00873       int e[4], bRev[4];
00874     } f[6] = {
00875       {{0, 9, 4, 8},  {false, false, true,  true}},
00876       {{1,10, 5, 9},  {false, false, true,  true}},
00877       {{2,11, 6,10},  {false, false, true,  true}},
00878       {{3, 8, 7,11},  {false, false, true,  true}},
00879       {{3, 2, 1, 0},  {true,  true,  true,  true}},
00880       {{4, 5, 6, 7},  {false, false, false, false}}
00881     };
00882     for ( fi = 0; fi < 6; fi++ )
00883     {
00884       ON_BrepEdge& e0 = brep->m_E[f[fi].e[0]];
00885       ON_BrepEdge& e1 = brep->m_E[f[fi].e[1]];
00886       ON_BrepEdge& e2 = brep->m_E[f[fi].e[2]];
00887       ON_BrepEdge& e3 = brep->m_E[f[fi].e[3]];
00888       ON_BrepVertex& v0 = brep->m_V[e0.m_vi[f[fi].bRev[0]?1:0]];
00889       ON_BrepVertex& v1 = brep->m_V[e1.m_vi[f[fi].bRev[1]?1:0]];
00890       ON_BrepVertex& v2 = brep->m_V[e2.m_vi[f[fi].bRev[2]?1:0]];
00891       ON_BrepVertex& v3 = brep->m_V[e3.m_vi[f[fi].bRev[3]?1:0]];
00892 
00893       si = brep->AddSurface( ON_NurbsSurfaceQuadrilateral( v0.point, v1.point, v2.point, v3.point ) );
00894       ON_Interval s = brep->m_S[si]->Domain(0);
00895       ON_Interval t = brep->m_S[si]->Domain(1);
00896       ON_2dPoint p0(s[0],t[0]);
00897       ON_2dPoint p1(s[1],t[0]);
00898       ON_2dPoint p2(s[1],t[1]);
00899       ON_2dPoint p3(s[0],t[1]);
00900 
00901       ON_BrepFace& face = brep->NewFace( si );
00902       ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, face );
00903 
00904       loop.m_pbox.m_min.x = s[0];
00905       loop.m_pbox.m_min.y = t[0];
00906       loop.m_pbox.m_min.z = 0.0;
00907 
00908       loop.m_pbox.m_max.x = s[1];
00909       loop.m_pbox.m_max.y = t[1];
00910       loop.m_pbox.m_max.z = 0.0;
00911 
00912       // south side of surface
00913       c2i = brep->AddTrimCurve( new ON_LineCurve( p0, p1 ) );
00914       ON_BrepTrim& trim0 = brep->NewTrim( e0, f[fi].bRev[0], loop, c2i );
00915       trim0.m_tolerance[0] = 0.0;
00916       trim0.m_tolerance[1] = 0.0;
00917       trim0.m_type = (trim0.m_vi[0] != trim0.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
00918       trim0.m_iso = ON_Surface::S_iso;
00919 
00920       // east side of surface
00921       c2i = brep->AddTrimCurve( new ON_LineCurve( p1, p2 ) );
00922       ON_BrepTrim& trim1 = brep->NewTrim( e1, f[fi].bRev[1], loop, c2i );
00923       trim1.m_tolerance[0] = 0.0;
00924       trim1.m_tolerance[1] = 0.0;
00925       trim1.m_type = (trim1.m_vi[0] != trim1.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
00926       trim1.m_iso = ON_Surface::E_iso;
00927 
00928       // north side of surface
00929       c2i = brep->AddTrimCurve( new ON_LineCurve( p2, p3 ) );
00930       ON_BrepTrim& trim2 = brep->NewTrim( e2, f[fi].bRev[2], loop, c2i );
00931       trim2.m_tolerance[0] = 0.0;
00932       trim2.m_tolerance[1] = 0.0;
00933       trim2.m_type = (trim2.m_vi[0] != trim2.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
00934       trim2.m_iso = ON_Surface::N_iso;
00935 
00936       // west side of surface
00937       c2i = brep->AddTrimCurve( new ON_LineCurve( p3, p0 ) );
00938       ON_BrepTrim& trim3 = brep->NewTrim( e3, f[fi].bRev[3], loop, c2i );
00939       trim3.m_tolerance[0] = 0.0;
00940       trim3.m_tolerance[1] = 0.0;
00941       trim3.m_type = (trim3.m_vi[0] != trim3.m_vi[1]) ? ON_BrepTrim::mated : ON_BrepTrim::singular;
00942       trim3.m_iso = ON_Surface::W_iso;
00943     }
00944     if ( !brep->IsValid() ) {
00945       if ( pBrep )
00946         pBrep->Destroy();
00947       else
00948         delete brep;
00949       brep = 0;
00950     }
00951   }
00952   else 
00953     brep = 0;
00954   return brep;
00955 }
00956 
00957 
00958 ON_Brep* ON_BrepWedge( const ON_3dPoint* corners, ON_Brep* pBrep )
00959 {
00960   ON_Brep* brep = 0;
00961 
00962   int vi, ei, ti, fi, si, c2i;
00963   
00964   if(corners)
00965   {
00966     // use the one passed in or make a new one
00967     if( pBrep ) 
00968     {
00969       pBrep->Destroy();
00970       brep = pBrep;
00971     }
00972     else
00973       brep = new ON_Brep();
00974     
00975     brep->m_C2.Reserve(18);
00976     brep->m_C3.Reserve(9);
00977     brep->m_S.Reserve(5);
00978     brep->m_V.Reserve(6);
00979     brep->m_E.Reserve(9);
00980     brep->m_L.Reserve(5);
00981     brep->m_T.Reserve(18);
00982     brep->m_F.Reserve(5);
00983 
00984     // vertices
00985     for ( vi = 0; vi < 6; vi++ )
00986     {
00987       brep->NewVertex( corners[vi], 0.0 );
00988     }
00989     
00990     // 3d edges around bottom e0 - e2
00991     for ( ei = 0; ei < 3; ei++ )
00992     {
00993       ON_BrepVertex& v0 = brep->m_V[ei];
00994       ON_BrepVertex& v1 = brep->m_V[(ei+1)%3];
00995       brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
00996       brep->NewEdge( v0, v1, ei, NULL, 0.0 );
00997     }
00998     // 3d edges around top e3 - e5
00999     for ( ei = 3; ei < 6; ei++ )
01000     {
01001       ON_BrepVertex& v0 = brep->m_V[ei];
01002       ON_BrepVertex& v1 = brep->m_V[ei==5?3:(ei+1)];
01003       brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
01004       brep->NewEdge( v0, v1, ei, NULL, 0.0 );
01005     }
01006     // 3d vertical edges e6 - e8
01007     for ( ei = 6; ei < 9; ei++ )
01008     {
01009       ON_BrepVertex& v0 = brep->m_V[ei-6];
01010       ON_BrepVertex& v1 = brep->m_V[ei-3];
01011       brep->m_C3.Append( new ON_LineCurve( v0.point, v1.point ) );
01012       brep->NewEdge( v0, v1, ei, NULL, 0.0 );
01013     }
01014 
01015     /*
01016     //
01017     //                      /v5    
01018     //                     /|\       
01019     //                    / | \     
01020     //                   e5 |  e4   
01021     //                  /   e8  \     
01022     //                 /__e3_____\  
01023     //               v3|    |    |v4     
01024     //                 |    |    |       
01025     //                 |    /v2  |   
01026     //                 e6  / \   e7   
01027     //                 |  /   \  |   
01028     //                 | e2    e1|   
01029     //                 |/       \|     
01030     //                 /____e0___\  
01031     //               v0           v1
01032     */
01033 
01034     struct {
01035       int e[4], bRev[4];
01036     } f[5] = {
01037       {{0, 7, 3, 6},  {false, false, true,  true}},  // vertical front
01038       {{1, 8, 4, 7},  {false, false, true,  true}},  // vertical right
01039       {{2, 6, 5, 8},  {false, false, true,  true}},  // vertical left
01040       {{2, 1, 0,-1},  {true,  true,  true,  true}},  // bottom
01041       {{3, 4, 5,-1},  {false, false, false, false}}  // top
01042     };
01043     for ( fi = 0; fi < 5; fi++ )
01044     {
01045       ON_BrepEdge* e0;
01046       ON_BrepEdge* e1;
01047       ON_BrepEdge* e2;
01048       ON_BrepEdge* e3=0;
01049 
01050       e0 = &brep->m_E[f[fi].e[0]];
01051       e1 = &brep->m_E[f[fi].e[1]];
01052       e2 = &brep->m_E[f[fi].e[2]];
01053       if( f[fi].e[3] >= 0)
01054         e3 = &brep->m_E[f[fi].e[3]];
01055 
01056       ON_BrepVertex* v0;
01057       ON_BrepVertex* v1;
01058       ON_BrepVertex* v2;
01059       ON_BrepVertex* v3=0;
01060 
01061       v0 = &brep->m_V[e0->m_vi[f[fi].bRev[0]?1:0]];
01062       v1 = &brep->m_V[e1->m_vi[f[fi].bRev[1]?1:0]];
01063       v2 = &brep->m_V[e2->m_vi[f[fi].bRev[2]?1:0]];
01064       if( f[fi].e[3] >= 0)
01065         v3 = &brep->m_V[e3->m_vi[f[fi].bRev[3]?1:0]];
01066 
01067       ON_NurbsSurface* srf;
01068 
01069       if( f[fi].e[3] >= 0)
01070         // 4 sided face
01071         srf = ON_NurbsSurfaceQuadrilateral( v0->point, v1->point, v2->point, v3->point);
01072       else
01073         // 3 sided face
01074         srf = ON_NurbsSurfaceQuadrilateral( v0->point, v1->point, v1->point + (v2->point - v0->point), v2->point);
01075 
01076       si = brep->AddSurface( srf);
01077 
01078       ON_Interval s = brep->m_S[si]->Domain(0);
01079       ON_Interval t = brep->m_S[si]->Domain(1);
01080       ON_2dPoint p0, p1, p2, p3;
01081       p0.Set(s[0],t[0]);
01082       p1.Set(s[1],t[0]);
01083       p2.Set(s[1],t[1]);
01084       p3.Set(s[0],t[1]);
01085 
01086       ON_BrepFace& face = brep->NewFace( si );
01087       ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, face );
01088 
01089       if( f[fi].e[3] >= 0)
01090       {
01091         // south side of surface
01092         c2i = brep->AddTrimCurve( new ON_LineCurve( p0, p1 ) );
01093         brep->NewTrim( *e0, f[fi].bRev[0], loop, c2i ).m_iso = ON_Surface::S_iso;
01094         
01095         // east side of surface
01096         c2i = brep->AddTrimCurve( new ON_LineCurve( p1, p2 ) );
01097         brep->NewTrim( *e1, f[fi].bRev[1], loop, c2i ).m_iso = ON_Surface::E_iso;
01098         
01099         // north side of surface
01100         c2i = brep->AddTrimCurve( new ON_LineCurve( p2, p3 ) );
01101         brep->NewTrim( *e2, f[fi].bRev[2], loop, c2i ).m_iso = ON_Surface::N_iso;
01102 
01103         // west side of surface
01104         c2i = brep->AddTrimCurve( new ON_LineCurve( p3, p0 ) );
01105         brep->NewTrim( *e3, f[fi].bRev[3], loop, c2i ).m_iso = ON_Surface::W_iso;
01106       }
01107       else
01108       {
01109         // south side of surface
01110         c2i = brep->AddTrimCurve( new ON_LineCurve( p0, p1 ) );
01111         brep->NewTrim( *e0, f[fi].bRev[0], loop, c2i ).m_iso = ON_Surface::S_iso;
01112         
01113         // diagonal from upper left to lower right
01114         c2i = brep->AddTrimCurve( new ON_LineCurve( p1, p3 ) );
01115         brep->NewTrim( *e1, f[fi].bRev[1], loop, c2i ).m_iso = ON_Surface::not_iso;
01116 
01117         // west side of surface
01118         c2i = brep->AddTrimCurve( new ON_LineCurve( p3, p0 ) );
01119         brep->NewTrim( *e2, f[fi].bRev[2], loop, c2i ).m_iso = ON_Surface::W_iso;
01120       }
01121     }
01122 
01123     // set trim m_type and m_tolerance[]
01124     for ( ti = 0; ti < brep->m_T.Count(); ti++ )
01125     {
01126       ON_BrepTrim& trim = brep->m_T[ti];
01127       trim.m_type =  ( trim.m_vi[0] != trim.m_vi[1] && trim.m_ei >= 0 )
01128                   ? ON_BrepTrim::mated
01129                   : ON_BrepTrim::singular;
01130       trim.m_tolerance[0] = 0.0;
01131       trim.m_tolerance[1] = 0.0;
01132     }
01133 
01134     if ( !brep->IsValid() ) {
01135       if ( pBrep )
01136         pBrep->Destroy();
01137       else
01138         delete brep;
01139       brep = 0;
01140     }
01141   }
01142   else 
01143     brep = 0;
01144   return brep;
01145 }
01146 
01147 
01148 ON_Brep* ON_BrepSphere( const ON_Sphere& sphere, ON_Brep* pBrep )
01149 {
01150   bool bArcLengthParameterization = true;
01151   ON_Brep* brep = NULL;
01152   if ( pBrep )
01153     pBrep->Destroy();
01154   ON_RevSurface* pRevSurface = sphere.RevSurfaceForm(bArcLengthParameterization);
01155   if ( pRevSurface )
01156   {
01157     brep = ON_BrepRevSurface( pRevSurface, false, false, pBrep );
01158     if ( !brep )
01159       delete pRevSurface;
01160   }
01161   return brep;
01162 }
01163 
01164 
01165 ON_Brep* ON_BrepTorus( const ON_Torus& torus, ON_Brep* pBrep )
01166 {
01167   ON_BOOL32 bArcLengthParameterization = true;
01168   ON_Brep* brep = NULL;
01169   if ( pBrep )
01170     pBrep->Destroy();
01171   ON_RevSurface* pRevSurface = torus.RevSurfaceForm();
01172   if ( pRevSurface )
01173   {
01174     if ( bArcLengthParameterization )
01175     {
01176       double r = fabs(torus.major_radius);
01177       if ( r <= ON_SQRT_EPSILON )
01178         r = 1.0;
01179       r *= ON_PI;
01180       pRevSurface->SetDomain(0,0.0,2.0*r);
01181       r = fabs(torus.minor_radius);
01182       if ( r <= ON_SQRT_EPSILON )
01183         r = 1.0;
01184       r *= ON_PI;
01185       pRevSurface->SetDomain(1,0.0,2.0*r);
01186     }
01187     brep = ON_BrepRevSurface( pRevSurface, false, false, pBrep );
01188     if ( !brep )
01189       delete pRevSurface;
01190   }
01191   return brep;
01192 }
01193 
01194 
01195 ON_Brep* ON_BrepCylinder( const ON_Cylinder& cylinder, 
01196                           ON_BOOL32 bCapBottom,
01197                           ON_BOOL32 bCapTop,
01198                           ON_Brep* pBrep )
01199 {
01200   ON_BOOL32 bArcLengthParameterization = true;
01201   ON_Brep* brep = NULL;
01202   if ( pBrep )
01203     pBrep->Destroy();
01204   ON_RevSurface* pRevSurface = cylinder.RevSurfaceForm();
01205   if ( pRevSurface )
01206   {
01207     if ( bArcLengthParameterization )
01208     {
01209       double r = fabs(cylinder.circle.radius);
01210       if ( r <= ON_SQRT_EPSILON )
01211         r = 1.0;
01212       pRevSurface->SetDomain(0,0.0,2.0*ON_PI*r);
01213     }
01214     brep = ON_BrepRevSurface( pRevSurface, bCapBottom, bCapTop, pBrep );
01215     if ( !brep )
01216       delete pRevSurface;
01217   }
01218   return brep;
01219 }
01220 
01221 
01222 ON_Brep* ON_BrepCone( const ON_Cone& cone, ON_BOOL32 bCapBase, ON_Brep* pBrep )
01223 {
01224   ON_BOOL32 bArcLengthParameterization = true;
01225   ON_Brep* brep = NULL;
01226   if ( pBrep )
01227     pBrep->Destroy();
01228   ON_RevSurface* pRevSurface = cone.RevSurfaceForm();
01229   if ( pRevSurface )
01230   {
01231     if ( bArcLengthParameterization )
01232     {
01233       double r = fabs(cone.radius);
01234       if ( r <= ON_SQRT_EPSILON )
01235         r = 1.0;
01236       pRevSurface->SetDomain(0,0.0,2.0*ON_PI*r);
01237     }
01238     brep = ON_BrepRevSurface( pRevSurface, bCapBase, bCapBase, pBrep );
01239     if ( !brep )
01240       delete pRevSurface;
01241   }
01242   return brep;
01243 }
01244 
01245 
01246 ON_Brep* ON_BrepRevSurface( 
01247           ON_RevSurface*& pRevSurface,
01248           ON_BOOL32 bCapStart,
01249           ON_BOOL32 bCapEnd,
01250           ON_Brep* pBrep 
01251           )
01252 {
01253   ON_Brep* brep = 0;
01254   if ( pBrep )
01255     pBrep->Destroy();
01256   if ( pRevSurface && pRevSurface->m_curve )
01257   {
01258     if ( pBrep )
01259       brep = pBrep;
01260     else
01261       brep = new ON_Brep();
01262 
01263     ON_BOOL32 bTransposed = pRevSurface->m_bTransposed;
01264     ON_Line axis = pRevSurface->m_axis;
01265     ON_3dPoint R[2];
01266     R[0] = pRevSurface->m_curve->PointAtStart();
01267     R[1] = pRevSurface->m_curve->PointAtEnd();
01268     if ( !pRevSurface->IsClosed(bTransposed?1:0) )
01269     {
01270       bCapStart = false;
01271       bCapEnd = false;
01272     }
01273 
01274     if ( !brep->Create(pRevSurface) )
01275     {
01276       if (!brep)
01277         delete brep;
01278       brep = 0;
01279     }
01280     else if ( bCapStart || bCapEnd )
01281     {
01282       // cap ends
01283       for ( int capcount = 0; capcount < 2; capcount++ )
01284       {
01285         int srf_trim_ti = -1;
01286         // capcount = 0 for bottom cap and 1 for top cap
01287         if ( capcount == 0 )
01288         {
01289           // cap circle at start of revolute
01290           if ( !bCapStart )
01291             continue;
01292           srf_trim_ti = (bTransposed) ? 3 : 0;
01293         }
01294         else
01295         {
01296           // cap circle at start of revolute
01297           if ( !bCapEnd )
01298             continue;
01299           srf_trim_ti = (bTransposed) ? 1 : 2;
01300         }
01301         if ( srf_trim_ti < 0 || srf_trim_ti >= brep->m_T.Count() )
01302           continue;
01303 
01304         if ( brep->m_T[srf_trim_ti].m_type != ON_BrepTrim::boundary )
01305           continue;
01306         if ( brep->m_T[srf_trim_ti].m_ei < 0 )
01307           continue;
01308         ON_BrepEdge& edge = brep->m_E[brep->m_T[srf_trim_ti].m_ei];
01309         if ( !edge.IsClosed() )
01310           continue;
01311 
01312         ON_Circle circle;
01313         {
01314           ON_Arc arc;
01315           const ON_Curve* edge_curve = edge.EdgeCurveOf();
01316           if ( 0 == edge_curve )
01317             continue;
01318           if ( !edge_curve->IsArc( NULL, &arc ) )
01319             continue;
01320           if ( !arc.IsCircle() )
01321             continue;
01322           circle = arc;
01323         }
01324 
01325         /*
01326         if ( capcount == 0 )
01327           circle.Reverse();
01328           */
01329         circle.Reverse();
01330 
01331         // create cap surface
01332         double radius = circle.radius;
01333         ON_NurbsSurface* pCapSurface = ON_NurbsSurfaceQuadrilateral( 
01334           circle.plane.PointAt(-radius,-radius),
01335           circle.plane.PointAt(+radius,-radius),
01336           circle.plane.PointAt(+radius,+radius),
01337           circle.plane.PointAt(-radius,+radius)
01338           );
01339         pCapSurface->m_knot[0][0] = -fabs(radius);
01340         pCapSurface->m_knot[0][1] =  fabs(radius);
01341         pCapSurface->m_knot[1][0] = pCapSurface->m_knot[0][0];
01342         pCapSurface->m_knot[1][1] = pCapSurface->m_knot[0][1];
01343 
01344         // trim curve circle
01345         circle.Create( ON_xy_plane, ON_origin, radius );
01346         ON_NurbsCurve* c2 = new ON_NurbsCurve();
01347         circle.GetNurbForm(*c2);
01348         c2->ChangeDimension(2);
01349 
01350         int si = brep->AddSurface(pCapSurface);
01351         int c2i = brep->AddTrimCurve(c2);
01352         ON_BrepFace& cap = brep->NewFace( si );
01353         ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, cap );
01354         ON_BrepTrim& trim = brep->NewTrim( edge, true, loop, c2i );
01355         for ( int eti = 0; eti < edge.m_ti.Count(); eti++ )
01356           brep->m_T[ edge.m_ti[eti] ].m_type = ON_BrepTrim::mated;
01357         trim.m_tolerance[0] = 0.0;
01358         trim.m_tolerance[1] = 0.0;
01359         trim.m_pbox.m_min.x = -radius;
01360         trim.m_pbox.m_min.y = -radius;
01361         trim.m_pbox.m_min.z = 0.0;
01362         trim.m_pbox.m_max.x = radius;
01363         trim.m_pbox.m_max.y = radius;
01364         trim.m_pbox.m_max.z = 0.0;
01365         trim.m__legacy_2d_tol = 0.0;
01366         trim.m__legacy_3d_tol = 0.0;
01367         loop.m_pbox = trim.m_pbox;
01368         brep->SetTrimTypeFlags(trim);
01369         brep->SetTrimIsoFlags(trim);
01370       }
01371     }
01372   }
01373   return brep;
01374 }
01375 
01376 
01377 
01378 static ON_BOOL32 AddC3Curve( const ON_Curve* c3, ON_SimpleArray<ON_Curve*>& C3 )
01379 {
01380   int j;
01381   if ( !c3 )
01382     return false;
01383   const int c3dim = c3->Dimension();
01384   if ( c3dim != 3 && c3dim != 2 )
01385     return false;
01386   if ( ON_PolyCurve::Cast(c3) )
01387   {
01388     const ON_PolyCurve* polycrv = static_cast<const ON_PolyCurve*>(c3);
01389     for ( j = 0; j < polycrv->Count(); j++ )
01390     {
01391       if ( !AddC3Curve( polycrv->SegmentCurve(j), C3 ) )
01392         return false;
01393     }
01394   }
01395   else if ( ON_PolylineCurve::Cast(c3) )
01396   {
01397     ON_Line line;
01398     //ON_LineCurve* linecrv = 0;
01399     const ON_PolylineCurve* pline = static_cast<const ON_PolylineCurve*>(c3);
01400     line.to = pline->m_pline[0];
01401     if ( 2 == c3dim )
01402       line.to.z = 0.0;
01403     for ( j = 1; j < pline->m_pline.Count(); j++ )
01404     {
01405       line.from = line.to;
01406       line.to = pline->m_pline[j];
01407       if ( 2 == c3dim )
01408         line.to.z = 0.0;
01409       if ( line.Length() > 0 )
01410         C3.Append( new ON_LineCurve(line) );
01411     }
01412   }
01413   else
01414   {
01415     ON_Curve* c3dup = c3->DuplicateCurve();
01416     if ( 0 == c3dup )
01417       return false;
01418     if ( 2 == c3dup->Dimension() )
01419     {
01420       c3dup->ChangeDimension(3);
01421       if ( 3 != c3dup->Dimension() )
01422       {
01423         delete c3dup;
01424         return false;
01425       }
01426     }
01427     C3.Append( c3dup );
01428   }
01429   return true;
01430 }
01431 
01432 bool ON_Brep::NewPlanarFaceLoop(
01433       int face_index,
01434       ON_BrepLoop::TYPE loop_type,
01435       ON_SimpleArray<ON_Curve*>& boundary,
01436       ON_BOOL32 bDuplicateCurves
01437       )
01438 {
01439   m_is_solid = 0;
01440   if ( face_index < 0 || face_index >= m_F.Count() || boundary.Count() < 1 )
01441     return false;
01442   ON_BrepFace& face = m_F[face_index];
01443   const ON_PlaneSurface* pPlaneSurface = ON_PlaneSurface::Cast(face.SurfaceOf());
01444   if ( !pPlaneSurface )
01445     return false;
01446   const ON_Plane plane(pPlaneSurface->m_plane);
01447 
01448   // get 3d edge curves
01449   ON_SimpleArray<ON_Curve*> C3( 2*boundary.Count() );
01450   ON_Curve* c3;
01451   int i, count = boundary.Count();
01452   for ( i = 0; i < count; i++ )
01453   {
01454     c3 = boundary[i];
01455     if ( !c3 )
01456       break;
01457     if ( bDuplicateCurves )
01458     {
01459       if ( !AddC3Curve( c3, C3 ) )
01460         break;
01461     }
01462     else
01463     {
01464       C3.Append(c3);
01465       boundary[i] = 0;
01466     }
01467   }
01468 
01469   if ( i < count )
01470   {
01471     ON_ERROR("ON_Brep::NewPlanarFaceLoop - null 3d curve in boundary[] array");
01472     if ( bDuplicateCurves )
01473     {
01474       for ( i = 0; i < C3.Count(); i++ )
01475         delete C3[i];
01476     }
01477     else
01478     {
01479       for ( i = 0; i < C3.Count(); i++ )
01480         boundary[i] = C3[i];
01481     }
01482     return false;
01483   }
01484 
01485   // get 2d trim curves
01486   ON_Xform proj_to_plane;
01487   proj_to_plane[0][0] = plane.xaxis.x;
01488   proj_to_plane[0][1] = plane.xaxis.y;
01489   proj_to_plane[0][2] = plane.xaxis.z;
01490   proj_to_plane[0][3] = -(plane.xaxis*plane.origin);
01491   proj_to_plane[1][0] = plane.yaxis.x;
01492   proj_to_plane[1][1] = plane.yaxis.y;
01493   proj_to_plane[1][2] = plane.yaxis.z;
01494   proj_to_plane[1][3] = -(plane.yaxis*plane.origin);
01495   proj_to_plane[2][0] = plane.zaxis.x;
01496   proj_to_plane[2][1] = plane.zaxis.y;
01497   proj_to_plane[2][2] = plane.zaxis.z;
01498   proj_to_plane[2][3] = -(plane.zaxis*plane.origin);
01499   proj_to_plane[3][0] = 0.0;
01500   proj_to_plane[3][1] = 0.0;
01501   proj_to_plane[3][2] = 0.0;
01502   proj_to_plane[3][3] = 1.0;
01503 
01504   count = C3.Count();
01505   ON_BoundingBox loop_pbox, cbox;
01506   ON_SimpleArray<double> edge_tol(count);
01507   ON_SimpleArray<ON_NurbsCurve*> C2( count );
01508   ON_NurbsCurve* c2;
01509   for ( i = 0; i < count; i++ )
01510   {
01511     c3 = C3[i];
01512     c2 = new ON_NurbsCurve();
01513     if ( !c3->GetNurbForm(*c2) )
01514       break;
01515     if ( !c2->Transform(proj_to_plane) )
01516       break;
01517     if ( !c2->GetBoundingBox(cbox) )
01518       break;
01519     double d = fabs(cbox.m_max.z);
01520     if ( d < fabs(cbox.m_min.z) )
01521       d = fabs(cbox.m_min.z);
01522     if ( d <= ON_ZERO_TOLERANCE )
01523       d = 0.0;
01524     edge_tol.Append( d );
01525     if ( !c2->ChangeDimension(2) )
01526       break;
01527     if ( !c2->MakePiecewiseBezier() )
01528       break;
01529     cbox.m_min.z = 0.0;
01530     cbox.m_max.z = 0.0;
01531     loop_pbox.Union(cbox);
01532     C2.Append(c2);
01533   }
01534   if ( i < count )
01535   {
01536     ON_ERROR("ON_Brep::NewPlanarFaceLoop - unable to create 2d trim curve");
01537     for ( i = 0; i < C2.Count(); i++ )
01538       delete C2[i];
01539     for ( i = 0; i < C3.Count(); i++ )
01540       delete C3[i];
01541     return false;
01542   }
01543 
01544   // add new vertices
01545   const int vi0 = m_V.Count();
01546   m_V.Reserve( vi0 + count );
01547   for ( i = 0; i < count; i++ )
01548     NewVertex( C3[i]->PointAtStart() );
01549 
01550   // add new edges
01551   const int ei0 = m_E.Count();
01552   m_E.Reserve( ei0 + count );
01553   for ( i = 0; i < count; i++ ) 
01554   {
01555     int c3i = AddEdgeCurve( C3[i] );
01556     ON_BrepEdge& edge = NewEdge( m_V[vi0+i], m_V[vi0+((i+1)%count)], c3i );
01557     edge.m_tolerance = edge_tol[i];
01558   }
01559 
01560   // add new trims
01561   ON_3dPoint P, Q;
01562   double trim_tol[2];
01563   ON_BrepLoop& loop = NewLoop( loop_type, face );
01564   loop.m_pbox = loop_pbox;
01565   for (i = 0; i < count; i++)
01566   {
01567     int c2i = AddTrimCurve( C2[i] );
01568     trim_tol[0] = 0.0;
01569     trim_tol[1] = 0.0;
01570     ON_NurbsCurve* c2 = C2[i];
01571     P = c2->PointAtEnd();
01572     Q = C2[(i+1)%count]->PointAtStart();
01573     double w = (c2->IsRational()) ? c2->Weight(c2->m_cv_count-1) : 1.0;
01574     if (w < ON_ZERO_TOLERANCE)
01575       w = 1.0;
01576     if (c2->IsRational())
01577       Q *= w;
01578     c2->SetCV( c2->m_cv_count-1, Q );
01579     if (c2->IsRational())
01580       c2->SetWeight(c2->m_cv_count-1, w);
01581     trim_tol[0] = fabs(P.x - Q.x);
01582     trim_tol[1] = fabs(P.y - Q.y);
01583     if ( trim_tol[0] <= ON_ZERO_TOLERANCE )
01584       trim_tol[0] = 0.0;
01585     if ( trim_tol[1] <= ON_ZERO_TOLERANCE )
01586       trim_tol[1] = 0.0;
01587     ON_BrepEdge& edge = m_E[ei0+i];
01588     ON_BrepTrim& trim = NewTrim( edge, false, loop, c2i );
01589     trim.m_type = ON_BrepTrim::boundary;
01590     trim.m_tolerance[0] = 1.1*trim_tol[0];
01591     trim.m_tolerance[1] = 1.1*trim_tol[1];
01592   }
01593   int loop_dir = LoopDirection( loop );
01594   switch ( loop_type )
01595   {
01596   case ON_BrepLoop::outer:
01597     if ( loop_dir < 0 )
01598       FlipLoop( loop );
01599     break;
01600   case ON_BrepLoop::inner:
01601     if ( loop_dir > 0 )
01602       FlipLoop( loop );
01603     break;
01604   case ON_BrepLoop::unknown:
01605     if ( loop_dir > 0 )
01606       loop.m_type = ON_BrepLoop::outer;
01607     else if ( loop_dir < 0 )
01608       loop.m_type = ON_BrepLoop::inner;
01609     break;
01610   default:
01611     // intentionally ignoring other ON_Brep::TYPE enum values
01612     break;
01613   }
01614 
01615   SetTrimIsoFlags();
01616   for ( i = vi0; i < m_V.Count(); i++ )
01617     SetVertexTolerance( m_V[i] );
01618 
01619   return true;
01620 }
01621 
01622 
01623 ON_Brep* ON_BrepTrimmedPlane( 
01624             const ON_Plane& plane, 
01625             ON_SimpleArray<ON_Curve*>& boundary,
01626             ON_BOOL32 bDuplicateCurves,
01627             ON_Brep* pBrep )
01628 {
01629   ON_Brep* brep;
01630   if ( pBrep )
01631   {
01632     pBrep->Destroy();
01633     brep = pBrep;
01634   }
01635   else
01636     brep = new ON_Brep();
01637 
01638   ON_PlaneSurface* s = new ON_PlaneSurface();
01639   s->m_plane = plane;
01640   s->SetDomain(0, -100.0, 100.0 ); // any domain and extents will do for now
01641   s->SetDomain(1, -100.0, 100.0 );
01642   s->SetExtents(0, s->Domain(0) );
01643   s->SetExtents(1, s->Domain(1) );
01644   const int si = brep->AddSurface(s);
01645   ON_BrepFace& face = brep->NewFace( si );
01646   face.DestroyRuntimeCache();
01647   if ( brep->NewPlanarFaceLoop( face.m_face_index, ON_BrepLoop::outer, boundary, bDuplicateCurves ) )
01648   {
01649     // set face domain
01650     const ON_BrepLoop* loop = brep->m_L.Last();
01651     s->SetDomain(0, loop->m_pbox.m_min.x, loop->m_pbox.m_max.x );
01652     s->SetDomain(1, loop->m_pbox.m_min.y, loop->m_pbox.m_max.y );
01653     s->SetExtents(0,s->Domain(0));
01654     s->SetExtents(1,s->Domain(1));
01655 
01656     // need to update trim m_iso flags because we changed surface shape
01657     brep->SetTrimIsoFlags(face);
01658   }
01659   else
01660   {
01661     if ( pBrep )
01662       pBrep->Destroy();
01663     else
01664       delete brep;
01665     brep = NULL;
01666   }
01667   return brep;
01668 }
01669 
01670 
01671 
01672 ON_Brep* ON_BrepTrimmedPlane( 
01673             const ON_Plane& plane, 
01674             const ON_Curve& boundary,
01675             ON_Brep* pBrep )
01676 {
01677   ON_SimpleArray<ON_Curve*> c;
01678   c.Append(const_cast<ON_Curve*>(&boundary));
01679   return ON_BrepTrimmedPlane( plane, c, true, pBrep );
01680 }
01681 
01682 
01683 ON_Brep* ON_BrepFromMesh( 
01684                          const ON_MeshTopology& mesh_topology, 
01685                          ON_BOOL32 bTrimmedTriangles,
01686                          ON_Brep* pBrep 
01687                          )
01688 {
01689   ON_BezierCurve edge_line(3,false,2);
01690   ON_BezierCurve trim_line(2,false,2);
01691   ON_Brep* brep = NULL;
01692   if ( pBrep )
01693     pBrep->Destroy();
01694   if ( mesh_topology.m_mesh && mesh_topology.IsValid() )
01695   {
01696     //const ON_Mesh& mesh = *mesh_topology.m_mesh;
01697     brep = (pBrep != NULL) ? pBrep : new ON_Brep();
01698     const int vertex_count = mesh_topology.TopVertexCount();
01699     const int edge_count = mesh_topology.TopEdgeCount();
01700     const int face_count = mesh_topology.TopFaceCount();
01701     brep->m_V.Reserve( vertex_count );
01702     brep->m_E.Reserve( edge_count );
01703     brep->m_C3.Reserve( edge_count );
01704     brep->m_F.Reserve( face_count );
01705     brep->m_L.Reserve( face_count );
01706     brep->m_T.Reserve( 4*face_count );
01707     brep->m_C2.Reserve( 4*face_count );
01708 
01709     int vi, ei, fi, c3i, c2i, si, lti, fvi[4];
01710     ON_Interval srf_dom[2];
01711     ON_3dPoint srf_2d_corner[4];
01712     ON_3dPoint srf_3d_corner[4];
01713     ON_Surface::ISO quad_iso[4] = {ON_Surface::S_iso,ON_Surface::E_iso,ON_Surface::N_iso,ON_Surface::W_iso};
01714     ON_Surface::ISO tri_iso[3] = {ON_Surface::S_iso,ON_Surface::E_iso,ON_Surface::not_iso};
01715 
01716     // May 1, 2012 Tim Fix for RR 104209
01717     // Use double precision vertexes from the mesh if they exist
01718     const ON_3dPointArray* pDPV = 0;
01719     if (mesh_topology.m_mesh->HasDoublePrecisionVertices() && mesh_topology.m_mesh->DoublePrecisionVerticesAreValid())
01720       pDPV = &mesh_topology.m_mesh->DoublePrecisionVertices();
01721 
01722     for ( vi = 0; vi < vertex_count; vi++ )
01723     {
01724       ON_3dPoint pt;
01725 
01726       // May 1, 2012 Tim Fix for RR 104209
01727       // Use double precision vertexes from the mesh if they exist
01728       const ON_MeshTopologyVertex& topvert = mesh_topology.m_topv[vi];
01729       if (0 != pDPV)
01730         pt = *pDPV->At(topvert.m_vi[0]);
01731       else
01732         pt = mesh_topology.m_mesh->m_V[topvert.m_vi[0]];
01733 
01734       brep->NewVertex( pt, 0.0 );
01735     }
01736 
01737     for ( ei = 0; ei < edge_count; ei++ )
01738     {
01739       const ON_MeshTopologyEdge& mesh_edge = mesh_topology.m_tope[ei];
01740       ON_BrepVertex& v0 = brep->m_V[mesh_edge.m_topvi[0]];
01741       ON_BrepVertex& v1 = brep->m_V[mesh_edge.m_topvi[1]];
01742       edge_line.SetCV(0, v0.point);
01743       edge_line.SetCV(1, v1.point);
01744       ON_Curve* pEdgeCurve = new ON_NurbsCurve( edge_line );
01745       c3i = brep->AddEdgeCurve( pEdgeCurve );
01746       ON_BrepEdge& edge = brep->NewEdge( v0, v1, c3i );    
01747       edge.m_tolerance = 0.0;
01748     }
01749 
01750     for ( fi = 0; fi < face_count; fi++ )
01751     {
01752       const ON_MeshTopologyFace& mesh_face = mesh_topology.m_topf[fi];
01753       // NOTE: mesh_face.m_topei[0] ENDS at vertex fvi[0].
01754       mesh_topology.GetTopFaceVertices( fi, fvi );
01755       ON_BOOL32 bTriangle = mesh_face.IsTriangle();
01756       srf_3d_corner[0] = brep->m_V[fvi[0]].point;
01757       srf_3d_corner[1] = brep->m_V[fvi[1]].point;
01758       srf_3d_corner[2] = brep->m_V[fvi[2]].point;
01759       if ( bTriangle )
01760       {
01761         if ( bTrimmedTriangles )
01762         {
01763           // trimmed triangle 
01764           srf_3d_corner[3] = srf_3d_corner[2] - srf_3d_corner[1] + srf_3d_corner[0];
01765         }
01766         else 
01767         {
01768           // singular triangle
01769           srf_3d_corner[3] = srf_3d_corner[0];
01770         }
01771       }
01772       else
01773       {
01774         // quad
01775         srf_3d_corner[3] = brep->m_V[fvi[3]].point;
01776       }
01777       ON_Surface* pSurface = ON_NurbsSurfaceQuadrilateral(
01778                               srf_3d_corner[0], srf_3d_corner[1], 
01779                               srf_3d_corner[2], srf_3d_corner[3] );
01780       srf_dom[0] = pSurface->Domain(0);
01781       srf_dom[1] = pSurface->Domain(1);
01782       srf_2d_corner[0].Set( srf_dom[0][0], srf_dom[1][0], 0.0 ); // SW parameter space corner
01783       srf_2d_corner[1].Set( srf_dom[0][1], srf_dom[1][0], 0.0 ); // SE parameter space corner
01784       srf_2d_corner[2].Set( srf_dom[0][1], srf_dom[1][1], 0.0 ); // NE parameter space corner
01785       srf_2d_corner[3].Set( srf_dom[0][0], srf_dom[1][1], 0.0 ); // NW parameter space corner
01786       si = brep->AddSurface( pSurface );
01787       ON_BrepFace& face = brep->NewFace( si );
01788       ON_BrepLoop& loop = brep->NewLoop( ON_BrepLoop::outer, face );
01789       loop.m_pbox.m_min = srf_2d_corner[0];
01790       loop.m_pbox.m_max = srf_2d_corner[2];
01791 
01792       int edge_index;
01793       int fei;
01794       if ( bTriangle && bTrimmedTriangles )
01795       {
01796         // trimmed triangle
01797         for ( lti = 0; lti < 3; lti++ )
01798         {
01799           fei = (lti+1)%3;
01800           edge_index = mesh_face.m_topei[fei];
01801           ON_BrepEdge& brep_edge = brep->m_E[edge_index];
01802           const ON_MeshTopologyEdge& mesh_edge = mesh_topology.m_tope[edge_index];
01803           trim_line.SetCV(0,srf_2d_corner[lti]);
01804           trim_line.SetCV(1,srf_2d_corner[(lti+1)%3]);
01805           ON_Curve* pTrimCurve = new ON_NurbsCurve( trim_line );
01806           c2i = brep->AddTrimCurve( pTrimCurve );
01807           ON_BrepTrim& trim = brep->NewTrim( brep_edge, 
01808                                              mesh_face.m_reve[fei]?true:false, 
01809                                              loop, 
01810                                              c2i );
01811           trim.m__legacy_2d_tol = 0.0;
01812           trim.m__legacy_3d_tol = 0.0;
01813           trim.m_tolerance[0] = 0.0;
01814           trim.m_tolerance[1] = 0.0;
01815           trim.m_iso = tri_iso[lti];
01816           trim.m_type = (mesh_edge.m_topf_count > 1) ? ON_BrepTrim::mated : ON_BrepTrim::boundary;
01817         }
01818       }
01819       else
01820       {
01821         for ( lti = 0; lti < 4; lti++ )
01822         {
01823           trim_line.SetCV(0,srf_2d_corner[lti]);
01824           trim_line.SetCV(1,srf_2d_corner[(lti+1)%4]);
01825           ON_Curve* c2 = new ON_NurbsCurve( trim_line );
01826           c2i = brep->AddTrimCurve( c2 );
01827           if ( bTriangle && lti == 3 )
01828           {
01829             // build a new singular edge
01830             brep->NewSingularTrim( brep->m_V[fvi[0]], 
01831                                                loop, 
01832                                                quad_iso[lti],
01833                                                c2i );
01834           }
01835           else 
01836           {
01837             fei = bTriangle ? ((lti+1)%3) : ((lti+1)%4);
01838             edge_index = mesh_face.m_topei[fei];
01839             ON_BrepEdge& brep_edge = brep->m_E[edge_index];
01840             const ON_MeshTopologyEdge& mesh_edge = mesh_topology.m_tope[edge_index];
01841             ON_BrepTrim& trim = brep->NewTrim( brep_edge, 
01842                                                mesh_face.m_reve[fei]?true:false, 
01843                                                loop, 
01844                                                c2i );
01845             trim.m__legacy_2d_tol = 0.0;
01846             trim.m__legacy_3d_tol = 0.0;
01847             trim.m_tolerance[0] = 0.0;
01848             trim.m_tolerance[1] = 0.0;
01849             trim.m_iso = quad_iso[lti];
01850             trim.m_type = (mesh_edge.m_topf_count > 1) ? ON_BrepTrim::mated : ON_BrepTrim::boundary;
01851           }
01852         }
01853       }      
01854     }
01855   }
01856   return brep;
01857 }
01858 
01859 static bool FoundSlitPair(ON_BrepLoop& L, int* t0, int* t1)
01860 
01861 {
01862   ON_Brep* B = L.Brep();
01863   if (!B) return false;
01864   const ON_Surface* Srf = L.SurfaceOf();
01865   double utol = 0.1*Srf->Domain(0).Length();
01866   double vtol = 0.1*Srf->Domain(1).Length();
01867   if (!Srf) return false;
01868   int i, count = L.m_ti.Count();
01869   for (i=0; i<count; i++){
01870     int s0 = L.m_ti[i];
01871     ON_BrepTrim& T0 = B->m_T[s0];
01872     if (T0.m_type != ON_BrepTrim::seam) continue;
01873     int s1 = (L.m_ti[(i+1)%count]);
01874     ON_BrepTrim& T1 = B->m_T[s1];
01875     if (T1.m_type != ON_BrepTrim::seam) continue;
01876     if (T0.m_vi[0] != T1.m_vi[1]) continue;
01877     if (T0.m_ei != T1.m_ei) continue;
01878     const ON_BrepEdge& E = B->m_E[T0.m_ei];
01879     if (E.m_ti.Count() != 2) continue;
01880     ON_2dPoint P0, P1;
01881     if (!B->GetTrim2dStart(s0, P0)) continue;
01882     if (!B->GetTrim2dEnd(s1, P1)) continue;
01883     if (fabs(P0[0] - P1[0]) > utol || fabs(P0[1] - P1[1]) > vtol) continue;
01884     *t0 = s0;
01885     *t1 = s1;
01886     return true;
01887   }
01888 
01889   return false;
01890 
01891 }
01892 
01893 
01894 bool ON_Brep::RemoveSlits(ON_BrepFace& F)
01895 
01896 {
01897   int i;
01898   bool rc = false;
01899   ON_SimpleArray<int> li = F.m_li;
01900   for (i=0; i<li.Count(); i++){
01901     ON_BrepLoop& L = m_L[li[i]];
01902     if (L.m_loop_index != li[i]) continue;
01903     if (L.m_type == ON_BrepLoop::slit) {
01904       DeleteLoop(L, true);
01905       rc = true;
01906       continue;
01907     }
01908     int t0, t1;
01909     while (FoundSlitPair(L, &t0, &t1)){
01910       rc = true;
01911       DeleteTrim(m_T[t0], true);
01912       DeleteTrim(m_T[t1], true);
01913     }
01914     if (L.m_ti.Count() == 0) DeleteLoop(L, true);
01915   }
01916   return rc;
01917 }
01918 
01919 
01920 
01921 bool ON_Brep::RemoveSlits()
01922 
01923 {
01924   bool rc = false;
01925   int i;
01926   for (i=0; i<m_F.Count(); i++){
01927     ON_BrepFace& F = m_F[i];
01928     if (F.m_face_index != i) continue;
01929     if (RemoveSlits(F))
01930       rc = true;
01931   }
01932   return rc;
01933 }
01934 
01935 bool ON_Brep::ChangeVertex( int old_vi, int new_vi, bool bClearTolerances )
01936 {
01937   if ( old_vi == new_vi )
01938     return true;
01939 
01940   ON_BrepVertex* old_v = Vertex(old_vi);
01941   ON_BrepVertex* new_v = Vertex(new_vi);
01942   
01943   if ( 0 == old_v )
01944     return false;
01945   if ( 0 == new_v )
01946     return false;
01947   if( old_v == new_v )
01948     return true;
01949 
01950   // clear type bits
01951   old_vi = (int)(old_v - m_V.Array()); // the (int) is for 64 bit size_t conversion
01952   new_vi = (int)(new_v - m_V.Array());
01953   if ( old_vi == new_vi )
01954     return true;
01955 
01956   int vei, evi, eti, tvi, ei;
01957 
01958   for ( vei = 0; vei < old_v->m_ei.Count(); vei++ )
01959   {
01960     ei = old_v->m_ei[vei];
01961     ON_BrepEdge* edge = Edge( ei );
01962     if ( 0 == edge )
01963       continue;
01964     // edges that start/end at the same vertex are listed twice in old_v->m_ei[].
01965     if ( edge->m_vi[0] == old_v->m_vertex_index )
01966       evi = 0;
01967     else if ( edge->m_vi[1] == old_v->m_vertex_index )
01968       evi = 1;
01969     else
01970       continue;
01971 
01972     // connect edge to new vertex
01973     new_v->m_ei.Append(ei);
01974     edge->m_vi[evi] = new_vi;
01975     if ( bClearTolerances )
01976     {
01977       edge->m_tolerance = ON_UNSET_VALUE;
01978       new_v->m_tolerance = ON_UNSET_VALUE;
01979     }
01980 
01981     for ( eti = 0; eti < edge->m_ti.Count(); eti++ )
01982     {
01983       ON_BrepTrim* trim = Trim( edge->m_ti[eti]);
01984       if ( 0 == trim )
01985         continue;
01986       tvi = trim->m_bRev3d ? 1-evi : evi;
01987       trim->m_vi[tvi] = new_vi;
01988       for(;;)
01989       {
01990         if ( 0 == tvi )
01991           trim = Trim(PrevTrim(trim->m_trim_index));
01992         else if ( 1 == tvi )
01993           trim = Trim(NextTrim(trim->m_trim_index));
01994         else
01995           break;
01996 
01997         if ( 0 == trim )
01998           break;
01999 
02000         if ( trim->m_ei >= 0 )
02001           break; // not singular
02002 
02003         if ( trim->m_vi[1-tvi] == old_vi )
02004           trim->m_vi[1-tvi] = new_vi;
02005         else
02006           break;
02007 
02008         if ( trim->m_vi[tvi] == old_vi )
02009           trim->m_vi[tvi] = new_vi;
02010         else
02011           break;
02012       }
02013     }
02014   }
02015   return true;
02016 }
02017 
02018 ON_BOOL32 ON_BrepEdge::SetStartPoint(ON_3dPoint start_point)
02019 {
02020   return false;
02021 }
02022 
02023 ON_BOOL32 ON_BrepEdge::SetEndPoint(ON_3dPoint end_point)
02024 {
02025   return false;
02026 }
02027 
02028 ON_BOOL32 ON_BrepTrim::SetStartPoint(ON_3dPoint point)
02029 {
02030   if ( 0 == m_brep )
02031     return false;
02032   if ( point.x == ON_UNSET_VALUE || point.y == ON_UNSET_VALUE )
02033     return false;
02034   if ( m_c2i < 0 || m_c2i >= m_brep->m_C2.Count() )
02035     return false;
02036   const ON_Curve* c2 = m_brep->m_C2[m_c2i];
02037   if ( 0 == c2 )
02038     return false;
02039 
02040   point.z = 0.0;
02041   ON_Interval domain = Domain();
02042   ON_3dPoint q = PointAtStart();
02043   q.z = 0;
02044   if ( point != q )
02045   {
02046     /*
02047     ON_NurbsCurve* nc2 = 0;
02048     if ( ProxyCurveDomain() == c2->Domain() && !ProxyCurveIsReversed() )
02049       nc2 = ON_NurbsCurve::Cast(c2);
02050     int use_count = (0 != nc2 ) ? m_brep->TrimCurveUseCount(m_c2i,2) : 0;
02051     if ( 0 == nc2 || use_count )
02052     {
02053       nc2 = NurbsCurve();
02054       if ( 0 == nc2 )
02055         return false;
02056     }
02057     nc2->ClampEnd();
02058     nc2->SetDomain(domain[0],domain[1]);
02059     if ( nc2->GetLocalClosestPoint( point, domain[0], &t ) )
02060     {
02061       nc2->Trim( ON_Interval(t,domain[1] );
02062     }
02063 */
02064   }
02065   return false;
02066 }
02067 
02068 ON_BOOL32 ON_BrepTrim::SetEndPoint(ON_3dPoint end_point)
02069 {
02070   return false;
02071 }
02072 
02073 
02074 bool ON_Brep::CloseTrimGap( ON_BrepTrim& trim0, ON_BrepTrim& trim1 )
02075 {
02076 
02077   // carefully close gap between end of prev_trim and start of next_trim
02078 
02079   // make sure trim0 and trim1 are adjacent trims in a trimming loop
02080   if ( trim0.m_vi[1] != trim1.m_vi[0] )
02081     return false;
02082   if ( trim0.m_li != trim1.m_li )
02083     return false;
02084   if ( trim0.m_li < 0 || trim0.m_li >= m_L.Count() )
02085     return false;
02086   ON_BrepLoop& loop = m_L[trim0.m_li];
02087   int lti;
02088   if ( loop.m_ti.Count() == 1 && trim0.m_trim_index == trim1.m_trim_index )
02089   {
02090     if ( trim0.IsClosed() )
02091       return true;
02092     lti = 0;
02093   }
02094   else
02095   {
02096     for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
02097     {
02098       if ( loop.m_ti[lti] == trim0.m_trim_index && loop.m_ti[(lti+1)%loop.m_ti.Count()] == trim1.m_trim_index )
02099         break;
02100     }
02101   }
02102   if ( lti >= loop.m_ti.Count() )
02103     return false;
02104 
02105   // determine where trims end and where they should meet.
02106   ON_Interval domain0 = trim0.Domain();
02107   ON_Interval domain1 = trim1.Domain();
02108   double t0 = domain0[1];
02109   double t1 = domain1[0];
02110   ON_3dPoint p0, p1;
02111   trim0.EvPoint( t0, p0 );
02112   trim1.EvPoint( t1, p1 );
02113   p0.z = 0.0;
02114   p1.z = 0.0;
02115   ON_3dPoint p = ON_Line(p0,p1).PointAt(0.5);
02116   if ( p0.x == p1.x )
02117     p.x = p0.x;
02118   if ( p0.y == p1.y )
02119     p.y = p0.y;
02120 
02121   int coord0_lock = -1;
02122   int coord1_lock = -1;
02123   switch(trim0.m_iso)
02124   {
02125   case ON_Surface::x_iso:
02126   case ON_Surface::W_iso:
02127   case ON_Surface::E_iso:
02128     // vertical iso curve - lock x coordinate
02129     coord0_lock = 0;
02130     break;
02131   case ON_Surface::y_iso:
02132   case ON_Surface::S_iso:
02133   case ON_Surface::N_iso:
02134     // horizontal iso curve - lock y coordinate
02135     coord0_lock = 1;
02136     break;
02137   default:
02138     coord0_lock = -1;
02139   }
02140 
02141   switch(trim1.m_iso)
02142   {
02143   case ON_Surface::x_iso:
02144   case ON_Surface::W_iso:
02145   case ON_Surface::E_iso:
02146     // vertical iso curve - lock x coordinate
02147     coord1_lock = 0;
02148     switch(coord0_lock)
02149     {
02150     case 0:
02151       if ( ON_Surface::x_iso == trim0.m_iso && ON_Surface::x_iso != trim1.m_iso )
02152         p.x = p1.x; // trim1 is on surface edge
02153       else if ( ON_Surface::x_iso != trim0.m_iso && ON_Surface::x_iso == trim1.m_iso )
02154         p.x = p0.x; // trim0 is on surface edge
02155       else
02156       {
02157         // longest one wins
02158         if ( p0.DistanceTo(trim0.PointAtStart()) >= p1.DistanceTo(trim1.PointAtEnd()) )
02159           p.x = p0.x;
02160         else
02161           p.x = p1.x;
02162       }
02163       break;
02164     case 1:
02165       p.x = p1.x;
02166       p.y = p0.y;
02167       break;
02168     default:
02169       p.x = p1.x;
02170       break;
02171     }
02172     break;
02173   case ON_Surface::y_iso:
02174   case ON_Surface::S_iso:
02175   case ON_Surface::N_iso:
02176     // horizontal iso curve - lock y coordinate
02177     coord1_lock = 1;
02178     switch(coord0_lock)
02179     {
02180     case 0:
02181       p.x = p0.x;
02182       p.y = p1.y;
02183       break;
02184     case 1:
02185       if ( ON_Surface::x_iso == trim0.m_iso && ON_Surface::x_iso != trim1.m_iso )
02186         p.y = p1.y; // trim1 is on surface edge
02187       else if ( ON_Surface::x_iso != trim0.m_iso && ON_Surface::x_iso == trim1.m_iso )
02188         p.y = p0.y; // trim0 is on surface edge
02189       else
02190       {
02191         // longest one wins
02192         if ( p0.DistanceTo(trim0.PointAtStart()) >= p1.DistanceTo(trim1.PointAtEnd()) )
02193           p.y = p0.y;
02194         else
02195           p.y = p1.y;
02196       }
02197       break;
02198     default:
02199       p.x = p1.x;
02200       break;
02201     }
02202     break;
02203   default:
02204     switch(coord0_lock)
02205     {
02206     case 0:
02207       p.x = p0.x;
02208       break;
02209     case 1:
02210       p.y = p0.y;
02211       break;
02212     }
02213     break;
02214   }
02215 
02216   if (ON_ComparePoint(3,0,&p.x,&p0.x))
02217   {
02218     trim0.SetEndPoint(p);
02219   }
02220   if (ON_ComparePoint(3,0,&p.x,&p1.x))
02221   {
02222     trim1.SetStartPoint(p);
02223   }
02224 
02225   return true;
02226 }
02227 
02228 bool ON_Brep::CollapseEdge( int edge_index, bool bCloseTrimGap, int vertex_index  )
02229 {
02230   ON_BrepEdge* edge = Edge(edge_index);
02231   if ( 0 == edge )
02232     return false;
02233   edge_index = edge->m_edge_index; // clear high bit
02234 
02235   if ( -1 == vertex_index )
02236     vertex_index = edge->m_vi[0];
02237   ON_BrepVertex* vertex = Vertex(vertex_index);
02238   if ( 0 == vertex )
02239     return false;
02240   vertex_index = vertex->m_vertex_index; // clear high bit
02241 
02242   int trim_count = edge->m_ti.Count();
02243   if ( trim_count > 0 )
02244   {
02245     ON_SimpleArray<int> ti(trim_count);
02246     ON_SimpleArray<int> li(trim_count);
02247     ON_SimpleArray<int> prev_ti(trim_count);
02248     ON_SimpleArray<int> next_ti(trim_count);
02249     int i, eti;
02250     for ( eti = 0; eti < trim_count; eti++ )
02251     {
02252       i = edge->m_ti[eti];
02253       if ( i < 0 || i >= m_T.Count() )
02254         continue;
02255       const ON_BrepTrim& trim = m_T[i];
02256       if ( trim.m_trim_index != i )
02257         return false;
02258       if ( trim.m_li < 0 || trim.m_li >= m_L.Count() )
02259         return false;
02260       i = PrevTrim(trim.m_trim_index);
02261       if ( i < 0 || i == trim.m_trim_index )
02262         return false;
02263       prev_ti.Append(i);
02264       i = NextTrim(trim.m_trim_index);
02265       if ( i < 0 || i == trim.m_trim_index )
02266         return false;
02267       next_ti.Append(i);
02268       ti.Append(trim.m_trim_index);
02269       li.Append(trim.m_li);
02270     }
02271 
02272     ChangeVertex(edge->m_vi[0], vertex_index, true);
02273     ChangeVertex(edge->m_vi[1], vertex_index, true);
02274     
02275     trim_count = ti.Count();
02276     for ( eti = 0; eti < trim_count; eti++ )
02277     {
02278       i = ti[eti];
02279       ON_BrepTrim& trim = m_T[i];
02280       //ON_BrepLoop& loop = m_L[li[eti]];
02281       ON_BrepTrim& prev_trim = m_T[prev_ti[eti]];
02282       ON_BrepTrim& next_trim = m_T[next_ti[eti]];
02283       DeleteTrim(trim,false);
02284       if ( bCloseTrimGap )
02285         CloseTrimGap(prev_trim,next_trim);
02286     }
02287   }
02288 
02289   DeleteEdge(*edge,true);
02290   return true;
02291 }
02292 
02293 int ON_Brep::RemoveWireEdges( bool bDeleteVertices )
02294 {
02295   int rc = 0;
02296   int ei, count = m_E.Count();
02297   for ( ei = 0; ei < count; ei++ )
02298   {
02299     if ( ei == m_E[ei].m_edge_index && 0 == m_E[ei].m_ti.Count() )
02300     {
02301       rc++;
02302       DeleteEdge( m_E[ei], bDeleteVertices );
02303     }
02304   }
02305   return rc;
02306 }
02307 
02308 int ON_Brep::RemoveWireVertices()
02309 {
02310   int rc = 0;
02311   int vi, count = m_V.Count();
02312   for ( vi = 0; vi < count; vi++ )
02313   {
02314     if ( vi == m_V[vi].m_vertex_index && 0 == m_V[vi].m_ei.Count() )
02315     {
02316       rc++;
02317       DeleteVertex( m_V[vi] );
02318     }
02319   }
02320   return rc;
02321 }
02322 
02323 
02324 bool ON_Brep::RemoveNesting(
02325         bool bExtractSingleSegments,
02326         bool bEdges, 
02327         bool bTrimCurves
02328         )
02329 {
02330   bool rc = false;
02331   // TODO
02332   int i, count;
02333   ON_PolyCurve* polycurve;
02334 
02335   if ( bEdges )
02336   {
02337     count = m_C3.Count();
02338     for ( i = 0; i < count; i++ )
02339     {
02340       polycurve = ON_PolyCurve::Cast(m_C3[i]);
02341       if ( 0 != polycurve )
02342       {
02343         if ( polycurve->RemoveNestingEx() )
02344           rc = true;
02345         if ( bExtractSingleSegments && 1 == polycurve->Count() )
02346         {
02347           // TODO - extract segment and update edge's proxy information
02348         }
02349       }
02350     }
02351   }
02352 
02353   if ( bTrimCurves )
02354   {
02355     count = m_C2.Count();
02356     for ( i = 0; i < count; i++ )
02357     {
02358       polycurve = ON_PolyCurve::Cast(m_C2[i]);
02359       if ( 0 != polycurve )
02360       {
02361         if ( polycurve->RemoveNestingEx() )
02362           rc = true;
02363         if ( bExtractSingleSegments && 1 == polycurve->Count() )
02364         {
02365           // TODO - extract segment and update trims's proxy information
02366         }
02367       }
02368     }
02369   }
02370 
02371   return rc;
02372 }
02373 
02374 static bool IsSlitTrim(const ON_BrepTrim& T)
02375 
02376 {
02377   int tid = T.m_trim_index;
02378   if (tid < 0)
02379     return false;
02380 
02381   const ON_BrepLoop* pL = T.Loop();
02382   if (!pL)
02383     return false;
02384 
02385   const ON_Brep* pB = T.Brep();
02386   if (!pB)
02387     return false;
02388 
02389   const ON_BrepEdge* pE = T.Edge();
02390   if (!pE || pE->m_edge_index < 0 || pE->m_ti.Count() != 2)
02391     return false;
02392 
02393   int atid = (pE->m_ti[0] == tid) ? pE->m_ti[1] : pE->m_ti[0];
02394   if (atid < 0)
02395     return false;
02396 
02397   const ON_BrepTrim& AT = pB->m_T[atid];
02398   if (AT.m_trim_index < 0)
02399     return false;
02400 
02401   if (AT.Loop() != pL)
02402     return false;
02403 
02404   const ON_Surface* pSrf = T.SurfaceOf();
02405   if (!pSrf)
02406     return false;
02407 
02408   double utol = 0.25*pSrf->Domain(0).Length();
02409   double vtol = 0.25*pSrf->Domain(1).Length();
02410 
02411   bool bRev = (T.m_bRev3d == AT.m_bRev3d) ? false : true;
02412 
02413   ON_2dPoint P = T.PointAtStart();
02414   ON_2dPoint AP = (bRev) ? AT.PointAtEnd() : AT.PointAtStart();
02415 
02416   if (fabs(P[0] - AP[0]) > utol)
02417     return false;
02418   if (fabs(P[1] - AP[1]) > vtol)
02419     return false;
02420 
02421   P = T.PointAtEnd();
02422   AP = (bRev) ? AT.PointAtStart() : AT.PointAtEnd();
02423 
02424   if (fabs(P[0] - AP[0]) > utol)
02425     return false;
02426   if (fabs(P[1] - AP[1]) > vtol)
02427     return false;
02428 
02429   return true;
02430 }
02431 
02432 static bool ON_BrepRemoveSlits(ON_BrepLoop& L)
02433 
02434 {
02435   if (L.m_loop_index < 0)
02436     return false;
02437   ON_BrepFace* pF = L.Face();
02438   if (!pF)
02439     return false;
02440   ON_Brep* pB = L.Brep();
02441   if (!pB)
02442     return false;
02443   //Check if anything or everything can be removed.
02444   ON_SimpleArray<bool> bIsSlit(L.m_ti.Count());
02445   ON_SimpleArray<int> slits(L.m_ti.Count());
02446   bool all_slits = true;
02447   bool some_slits = false;
02448   int tcount = L.m_ti.Count();
02449   int i;
02450   for (i=0; i<tcount; i++){
02451     ON_BrepTrim& T = pB->m_T[L.m_ti[i]];
02452     if (IsSlitTrim(T)){
02453       bIsSlit.Append(true);
02454       slits.Append(T.m_trim_index);
02455       some_slits = true;
02456     }
02457     else {
02458       bIsSlit.Append(false);
02459       all_slits = false;
02460     }
02461   }
02462 
02463   if (all_slits){
02464     pB->DeleteLoop(L, true);
02465     return true;
02466   }
02467 
02468   if (!some_slits)
02469     return false;
02470 
02471   ON_SimpleArray<bool> bUsed = bIsSlit;
02472 
02473   ON_ClassArray<ON_SimpleArray<int> > NewLoops;
02474 
02475   //bool done = false;
02476   int b = 0;
02477   while (b < tcount){
02478     int start_trim = -1;
02479     for (i=0; i<tcount; i++){
02480       if (!bUsed[i]){
02481         start_trim = i;
02482         break;
02483       }
02484     }
02485     if (start_trim < 0)
02486       break;
02487     ON_SimpleArray<int>& nl = NewLoops.AppendNew();
02488     b++;
02489     nl.Append(start_trim);
02490     bUsed[start_trim] = true;
02491     int next_trim = (start_trim+1)%tcount;
02492     int c = 0;
02493     while (c < tcount){
02494       if (!bUsed[next_trim]){
02495         nl.Append(next_trim);
02496         bUsed[next_trim] = true;
02497         next_trim = (next_trim+1)%tcount;
02498         c++;
02499         continue;
02500       }
02501       if (next_trim == start_trim)
02502         break;
02503       if (bIsSlit[next_trim]){
02504         int this_trim = next_trim;
02505         ON_BrepTrim& T = pB->m_T[L.m_ti[next_trim]];
02506         ON_BrepEdge* pE = T.Edge();
02507         int atid = (pE->m_ti[0] == T.m_trim_index) ? pE->m_ti[1] : pE->m_ti[0];
02508         next_trim = -1;
02509         for (i=0; i<tcount; i++){
02510           if (L.m_ti[i] == atid){
02511             next_trim = i;
02512             break;
02513           }
02514         }
02515         if (next_trim == -1)
02516           return false;
02517         if (next_trim > this_trim)
02518           c += next_trim - this_trim;
02519         else c += tcount - this_trim + next_trim;
02520         next_trim = (next_trim+1)%tcount;
02521         c++;
02522       }
02523     }
02524     if (c >= tcount)
02525       return false;
02526   }
02527   if (b >= tcount)
02528     return false;
02529 
02530   for (i=0; i<NewLoops.Count(); i++){
02531     ON_SimpleArray<int>& nl = NewLoops[i];
02532     int j;
02533     for (j=0; j<nl.Count(); j++)
02534       nl[j] = L.m_ti[nl[j]];
02535   }
02536 
02537   bool bOuter = (L.m_type == ON_BrepLoop::outer) ? true : false;
02538 
02539   for (i=0; i<slits.Count(); i++){
02540     ON_BrepTrim& T = pB->m_T[slits[i]];
02541     T.m_li = -1;
02542     pB->DeleteTrim(T, true);
02543   }
02544 
02545   //int loop_count = pB->m_L.Count();
02546 
02547   L.m_ti.SetCount(0);
02548   pB->DeleteLoop(L, true);
02549 
02550   for (i=0; i<NewLoops.Count(); i++){
02551     ON_BrepLoop& nL = pB->NewLoop(ON_BrepLoop::unknown, *pF);
02552     ON_SimpleArray<int>& nl = NewLoops[i];
02553     nL.m_ti = nl;
02554     int j;
02555     for (j=0; j<nl.Count(); j++){
02556       ON_BrepTrim& T = pB->m_T[nl[j]];
02557       T.m_li = nL.m_loop_index;
02558     }
02559     nL.m_type = pB->ComputeLoopType(nL);
02560     if (bOuter && nL.m_type == ON_BrepLoop::outer){
02561       int a = pF->m_li[0];
02562       pF->m_li[0] = nL.m_loop_index;
02563       for (j=pF->m_li.Count()-1; j>0; j--){
02564         if (pF->m_li[j] == nL.m_loop_index){
02565           pF->m_li[j] = a;
02566           break;
02567         }
02568       }
02569     }
02570     pB->SetTrimBoundingBoxes(nL, true);
02571   }
02572   return true;
02573 }
02574 
02575 //This removes all slit trims  from F that are not joined to another face.
02576 //Unlike ON_Brep::RemoveSlits(), this will remove slit pairs from a loop in cases 
02577 //that will result in the creation of more loops. Caller is responsible for calling 
02578 //ON_Brep::Compact() to get rid of deleted trims and loops.
02579 
02580 bool ON_BrepRemoveSlits(ON_BrepFace& F)
02581 
02582 {
02583   //For each loop, look for slit pairs that fall between non slits and 
02584   //break the loop at the pair.
02585   //After all loops have been split, call ON_Brep::RemoveSlits() on the result.
02586 
02587   if (F.m_face_index < 0)
02588     return false;
02589   ON_Brep* pB = F.Brep();
02590   if (!pB)
02591     return false;
02592   bool rc = false;
02593   int loop_count = F.m_li.Count();
02594   int i;
02595   for (i=0; i<loop_count; i++){
02596     ON_BrepLoop& L = pB->m_L[F.m_li[i]];
02597     if (L.m_loop_index < 0)
02598       continue;
02599     if (ON_BrepRemoveSlits(L))
02600       rc = true;
02601   }
02602   return rc;
02603 }
02604 
02605 
02606 static void CreateNewTrimList(const ON_BrepLoop& L0, int tid0,//into L0.m_ti
02607                                const ON_BrepLoop& L1, int tid1,//into L1.m_ti
02608                                ON_SimpleArray<int>& new_tids //into brep.m_T
02609                                )
02610 
02611 {
02612   new_tids.Reserve(L0.m_ti.Count() + L1.m_ti.Count() - 2);
02613 
02614   int count = L0.m_ti.Count();
02615   int i;
02616   for (i=0; i<count-1; i++)
02617     new_tids.Append(L0.m_ti[(tid0+1+i)%count]);
02618 
02619   count = L1.m_ti.Count();
02620   for (i=0; i<count-1; i++)
02621     new_tids.Append(L1.m_ti[(tid1+1+i)%count]);
02622 
02623   return;
02624 }
02625 
02626 int ON_BrepMergeFaces(ON_Brep& B, int fid0, int fid1)
02627 
02628 {
02629   if (fid0 == fid1)
02630     return -1;
02631 
02632   if (fid0 < 0 || fid0 >= B.m_F.Count())
02633     return -1;
02634   ON_BrepFace& F0 = B.m_F[fid0];
02635   if (F0.m_face_index < 0)
02636     return -1;
02637 
02638   if (fid1 < 0 || fid1 >= B.m_F.Count())
02639     return -1;
02640   ON_BrepFace& F1 = B.m_F[fid1];
02641   if (F1.m_face_index < 0)
02642     return -1;
02643 
02644   if (F0.m_si != F1.m_si)
02645     return -1;
02646 
02647   //Find a manifold edge that joins the two faces and combine the loops by removing 
02648   //the trims at that edge.
02649 
02650   ON_BrepEdge* pE = 0;
02651 
02652   int li;
02653   int tid0 = -1, tid1 = -1;
02654   for (li=0; li<F0.m_li.Count() && !pE; li++){
02655     ON_BrepLoop& L = B.m_L[F0.m_li[li]];
02656     int ti;
02657     for (ti=0; ti<L.m_ti.Count() && !pE; ti++){
02658       ON_BrepTrim& T0 = B.m_T[L.m_ti[ti]];
02659       ON_BrepEdge* pEE = T0.Edge();
02660       if (!pEE || pEE->m_ti.Count() != 2)
02661         continue;
02662       tid0 =T0.m_trim_index;
02663       tid1 = (pEE->m_ti[0] == tid0) ? pEE->m_ti[1] : pEE->m_ti[0];
02664       if (tid0 < 0 || tid1 < 0)
02665         continue;
02666       ON_BrepTrim& T1 = B.m_T[tid1];
02667       if (T1.FaceIndexOf() == fid1 && T0.m_bRev3d != T1.m_bRev3d){
02668         pE = pEE;
02669         break;
02670       }
02671     }
02672   }
02673 
02674   if (!pE || tid0 < 0 || tid1 < 0)
02675     return -1;
02676 
02677   ON_BrepTrim& T0 = B.m_T[tid0];
02678   ON_BrepTrim& T1 = B.m_T[tid1];
02679 
02680   int lid0 = T0.m_li;
02681   if (lid0 < 0)
02682     return -1;
02683   ON_BrepLoop& L0 = B.m_L[lid0];
02684   if (L0.m_loop_index < 0)
02685     return -1;
02686   if (L0.Face() != &F0)
02687     return -1;
02688   int i;
02689   int ti0 = -1;
02690   for (i=0; i<L0.m_ti.Count(); i++){
02691     const ON_BrepTrim& T = B.m_T[L0.m_ti[i]];
02692     if (T.m_trim_index == tid0){
02693       ti0 = i;
02694       break;
02695     }
02696   }
02697   if (ti0 < 0)
02698     return -1;
02699 
02700   int lid1 = T1.m_li;
02701   if (lid1 < 0)
02702     return -1;
02703   ON_BrepLoop& L1 = B.m_L[lid1];
02704   if (L1.m_loop_index < 0)
02705     return -1;
02706   if (L1.Face() != &F1)
02707     return -1;
02708   int ti1 = -1;
02709   for (i=0; i<L1.m_ti.Count(); i++){
02710     const ON_BrepTrim& T = B.m_T[L1.m_ti[i]];
02711     if (T.m_trim_index == tid1){
02712       ti1 = i;
02713       break;
02714     }
02715   }
02716   if (ti1 < 0)
02717     return -1;
02718 
02719 
02720   ON_SimpleArray<int> new_tids;
02721   CreateNewTrimList(L0, ti0, L1, ti1, new_tids);
02722 
02723   ON_BrepLoop* pL;
02724   ON_BrepLoop* pD;
02725   ON_BrepFace* pF;
02726   ON_BrepFace* pDF;
02727   int rc;
02728   if (L1.m_type != ON_BrepLoop::inner){
02729     pL = &L0;
02730     pD = &L1;
02731     rc = fid0;
02732     pF = &F0;
02733     pDF = &F1;
02734   }
02735   else {
02736     pL = &L1;
02737     pD = &L0;
02738     rc = fid1;
02739     pF = &F1;
02740     pDF = &F0;
02741   }
02742   pL->m_ti = new_tids;
02743   pL->m_pbox.Destroy();
02744   pD->m_ti.SetCount(0);
02745   T0.m_li = -1;
02746   T1.m_li = -1;
02747   B.DeleteTrim(T0, true);
02748   B.DeleteTrim(T1, true);
02749   B.DeleteLoop(*pD, true);
02750   for (i=0; i<pL->m_ti.Count(); i++)
02751     B.m_T[pL->m_ti[i]].m_li = pL->m_loop_index;
02752   for (i=0; i<pDF->m_li.Count(); i++){
02753     ON_BrepLoop& ML = B.m_L[pDF->m_li[i]];
02754     ML.m_fi = rc;
02755     pF->m_li.Append(ML.m_loop_index);
02756   }
02757   pDF->m_li.SetCount(0);
02758   B.DeleteFace(*pDF, true);
02759   ON_BrepRemoveSlits(B.m_F[rc]);
02760 
02761   B.SetTrimBoundingBoxes(B.m_F[rc], true);
02762 
02763   return rc;
02764 
02765 }
02766 
02767 typedef int srf_face[2];
02768 
02769 static int sfsort(const srf_face* a, const srf_face* b)
02770 {
02771   if ((*a)[0] < (*b)[0])
02772     return -1;
02773   if ((*b)[0] < (*a)[0])
02774     return 1;
02775   return 0;
02776 }
02777 
02778 bool ON_BrepMergeFaces(ON_Brep& B)
02779 
02780 {
02781   bool rc = false;
02782   ON_SimpleArray<srf_face> SF(B.m_F.Count());
02783   int i;
02784   for (i=0; i<B.m_F.Count(); i++){
02785     const ON_BrepFace& F = B.m_F[i];
02786     if (F.m_face_index < 0)
02787       continue;
02788     if (F.m_si < 0)
02789       continue;
02790     srf_face& sf = SF.AppendNew();
02791     sf[0] = F.m_si;
02792     sf[1] = i;
02793   }
02794   if (SF.Count() < 2)
02795     return false;
02796   SF.QuickSort(sfsort);
02797   //int si = SF[0][0];
02798   int start_i = 0;
02799   while (start_i<SF.Count()){
02800     int next_i = start_i+1;
02801     while (next_i<SF.Count() && SF[next_i][0] == SF[start_i][0])
02802       next_i++;
02803     if (next_i == start_i+1){
02804       start_i++;
02805       continue;
02806     }
02807     for (i=start_i; i<next_i-1; i++){
02808       int j;
02809       for (j=i+1; j<next_i; j++){
02810         int new_id = ON_BrepMergeFaces(B, SF[i][1], SF[j][1]);
02811         if (new_id < 0)
02812           continue;
02813         SF[j][1] = new_id;
02814         rc = true;
02815         break;
02816       }
02817     }
02818     start_i = next_i;
02819   }
02820 
02821   ON_BrepMergeAllEdges(B);
02822   return rc;
02823 }
02824 
02825 
02826 static int MergeAdjacentEdge(ON_Brep& B, int eid)
02827 
02828 {
02829   ON_BrepEdge& E = B.m_E[eid];
02830   if (!E.IsValid())
02831     return -1;
02832 
02833   /*
02834   if (E.m_edge_user_i >= 0)
02835     return -1;
02836     */
02837 
02838   if (E.m_ti.Count() == 0)
02839     return -1;
02840 
02841   int i;
02842   for (i=0; i<2; i++){
02843     int neid = B.NextEdge(eid, i);
02844     if (neid >= 0){
02845       ON_BrepEdge* pE = B.CombineContiguousEdges(eid, neid);
02846       if (pE)
02847         return pE->m_edge_index;
02848     }
02849   }
02850 
02851   return -1;
02852 }
02853 
02854 //Merges all possible edges
02855 void ON_BrepMergeAllEdges(ON_Brep& B)
02856 
02857 {
02858   int i;
02859   int count = B.m_E.Count();
02860   for (i=0; i<count; i++){
02861     int eid = i;
02862     int j = 0;
02863     while (eid >= 0 && j < count){
02864       eid = MergeAdjacentEdge(B, eid);
02865       j++;
02866     }
02867   }
02868   return;
02869 }
02870 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:00