00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00023
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
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
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
00138 srf->CollapseSide( 1 );
00139 }
00140
00141 if ( vid[1] == vid[2] )
00142 {
00143
00144 srf->CollapseSide( 3 );
00145 }
00146
00147
00148 int eid[4] = {-1,-1,-1,-1};
00149 ON_BOOL32 bRev3d[4] = {false,false,false,false};
00150
00151
00152 eid[0] = edgeA.m_edge_index;
00153 bRev3d[0] = bRevEdgeA;
00154
00155
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
00164 eid[2] = edgeB.m_edge_index;
00165 bRev3d[2] = !bRevEdgeB;
00166
00167
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
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
00216 int eid[4] = {-1,-1,-1,-1};
00217 ON_BOOL32 bRev3d[4] = {false,false,false,false};
00218
00219
00220 eid[0] = edge.m_edge_index;
00221 bRev3d[0] = bRevEdge;
00222
00223
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
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
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
00309
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
00334
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
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];
00503 ON_BOOL32 bIsClosed[2];
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;
00511 }
00512
00513
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
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
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
00616 bool bEdgeIsClosed[4];
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:
00639 c3[i] = pSurface->IsoCurve(i%2, v[0]);
00640 break;
00641 case 1:
00642 c3[i] = pSurface->IsoCurve(i%2, u[1]);
00643 break;
00644 case 2:
00645 c3[i] = pSurface->IsoCurve(i%2, v[1]);
00646 break;
00647 case 3:
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
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
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
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
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
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
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
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
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
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
00985 for ( vi = 0; vi < 6; vi++ )
00986 {
00987 brep->NewVertex( corners[vi], 0.0 );
00988 }
00989
00990
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
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
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
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034 struct {
01035 int e[4], bRev[4];
01036 } f[5] = {
01037 {{0, 7, 3, 6}, {false, false, true, true}},
01038 {{1, 8, 4, 7}, {false, false, true, true}},
01039 {{2, 6, 5, 8}, {false, false, true, true}},
01040 {{2, 1, 0,-1}, {true, true, true, true}},
01041 {{3, 4, 5,-1}, {false, false, false, false}}
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
01071 srf = ON_NurbsSurfaceQuadrilateral( v0->point, v1->point, v2->point, v3->point);
01072 else
01073
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
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
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
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
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
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
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
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
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
01283 for ( int capcount = 0; capcount < 2; capcount++ )
01284 {
01285 int srf_trim_ti = -1;
01286
01287 if ( capcount == 0 )
01288 {
01289
01290 if ( !bCapStart )
01291 continue;
01292 srf_trim_ti = (bTransposed) ? 3 : 0;
01293 }
01294 else
01295 {
01296
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
01327
01328
01329 circle.Reverse();
01330
01331
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
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
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
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
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
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
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
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
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 );
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
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
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
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
01717
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
01727
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
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
01764 srf_3d_corner[3] = srf_3d_corner[2] - srf_3d_corner[1] + srf_3d_corner[0];
01765 }
01766 else
01767 {
01768
01769 srf_3d_corner[3] = srf_3d_corner[0];
01770 }
01771 }
01772 else
01773 {
01774
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 );
01783 srf_2d_corner[1].Set( srf_dom[0][1], srf_dom[1][0], 0.0 );
01784 srf_2d_corner[2].Set( srf_dom[0][1], srf_dom[1][1], 0.0 );
01785 srf_2d_corner[3].Set( srf_dom[0][0], srf_dom[1][1], 0.0 );
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
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
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
01951 old_vi = (int)(old_v - m_V.Array());
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
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
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;
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
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
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
02078
02079
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
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
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
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
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;
02153 else if ( ON_Surface::x_iso != trim0.m_iso && ON_Surface::x_iso == trim1.m_iso )
02154 p.x = p0.x;
02155 else
02156 {
02157
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
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;
02187 else if ( ON_Surface::x_iso != trim0.m_iso && ON_Surface::x_iso == trim1.m_iso )
02188 p.y = p0.y;
02189 else
02190 {
02191
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;
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;
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
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
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
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
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
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
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
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
02576
02577
02578
02579
02580 bool ON_BrepRemoveSlits(ON_BrepFace& F)
02581
02582 {
02583
02584
02585
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,
02607 const ON_BrepLoop& L1, int tid1,
02608 ON_SimpleArray<int>& new_tids
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
02648
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
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
02835
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
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