00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019
00021
00023
00024 ON_OBJECT_IMPLEMENT(ON_BrepVertex,ON_Point,"60B5DBC0-E660-11d3-BFE4-0010830122F0");
00025
00026 static bool ON_BrepIsNotValid()
00027 {
00028 return ON_IsNotValid();
00029 }
00030
00031
00032 ON_BrepVertex::ON_BrepVertex()
00033 : m_vertex_index(-1),
00034 m_tolerance(ON_UNSET_VALUE)
00035 {
00036 memset(&m_vertex_user,0,sizeof(m_vertex_user));
00037 }
00038
00039 ON_BrepVertex::ON_BrepVertex( int vertex_index )
00040 : m_vertex_index(vertex_index),
00041 m_tolerance(ON_UNSET_VALUE)
00042 {
00043 memset(&m_vertex_user,0,sizeof(m_vertex_user));
00044 }
00045
00046 unsigned int ON_BrepVertex::SizeOf() const
00047 {
00048 unsigned int sz = ON_Geometry::SizeOf();
00049 sz += (sizeof(*this) - sizeof(ON_Geometry));
00050 sz += m_ei.SizeOfArray();
00051 return sz;
00052 }
00053
00054 ON_BrepVertex& ON_BrepVertex::operator=(const ON_BrepVertex& src)
00055 {
00056 if ( &src != this ) {
00057 ON_Point::operator=(src);
00058 m_vertex_user = src.m_vertex_user;
00059 m_vertex_index = src.m_vertex_index;
00060 m_ei = src.m_ei;
00061 m_tolerance = src.m_tolerance;
00062 }
00063 return *this;
00064 }
00065
00066 ON_BOOL32
00067 ON_BrepVertex::IsValid( ON_TextLog* text_log ) const
00068 {
00069 if (m_vertex_index < 0)
00070 {
00071 if ( text_log )
00072 text_log->Print("ON_BrepVertex m_vertex_index = %d. Should be >= 0\n",m_vertex_index);
00073 return ON_BrepIsNotValid();
00074 }
00075 const int ve_count = EdgeCount();
00076 int vei, ei;
00077 for ( vei = 0; vei < ve_count; vei++ ) {
00078 ei = m_ei[vei];
00079 if ( ei < 0 )
00080 {
00081 if ( text_log )
00082 text_log->Print("ON_BrepVertex m_ei[%d] = %d. m_ei[] values should be >= 0\n",vei,ei);
00083 return ON_BrepIsNotValid();
00084 }
00085 }
00086 return ON_Point::IsValid(text_log);
00087 }
00088
00089 void
00090 ON_BrepVertex::Dump( ON_TextLog& dump ) const
00091 {
00092 dump.Print("ON_BrepVertex[%d]: ",m_vertex_index);
00093 dump.Print( point );
00094 dump.Print("\n");
00095 }
00096
00097
00098 bool
00099 ON_BrepVertex::SetPoint( const ON_3dPoint& p )
00100 {
00101 point = p;
00102 m_tolerance = ON_UNSET_VALUE;
00103 return true;
00104 }
00105
00106 ON_3dPoint
00107 ON_BrepVertex::Point() const
00108 {
00109 return point;
00110 }
00111
00112 double
00113 ON_BrepVertex::Tolerance() const
00114 {
00115 return m_tolerance;
00116 }
00117
00118 int
00119 ON_BrepVertex::EdgeCount() const
00120 {
00121 return m_ei.Count();
00122 }
00123
00125
00127
00128 ON_OBJECT_IMPLEMENT(ON_BrepEdge,ON_CurveProxy,"60B5DBC1-E660-11d3-BFE4-0010830122F0");
00129
00130 ON_BrepEdge::ON_BrepEdge() : ON_CurveProxy(0),
00131 m_edge_index(-1),
00132 m_c3i(-1),
00133 m_tolerance(ON_UNSET_VALUE),
00134 m_brep(0)
00135 {
00136 memset(&m_edge_user,0,sizeof(m_edge_user));
00137 m_vi[0] = m_vi[1] = -1;
00138 }
00139
00140 ON_BrepEdge::ON_BrepEdge(int edge_index ) : ON_CurveProxy(0),
00141 m_edge_index(edge_index),
00142 m_c3i(-1),
00143 m_tolerance(ON_UNSET_VALUE),
00144 m_brep(0)
00145 {
00146 memset(&m_edge_user,0,sizeof(m_edge_user));
00147 m_vi[0] = m_vi[1] = -1;
00148 }
00149
00150 ON::object_type ON_BrepEdge::ObjectType() const
00151 {
00152
00153
00154 return ON::curve_object;
00155 }
00156
00157 unsigned int ON_BrepEdge::SizeOf() const
00158 {
00159 unsigned int sz = ON_CurveProxy::SizeOf();
00160 sz = (sizeof(*this) - sizeof(ON_CurveProxy));
00161 sz += m_ti.SizeOfArray();
00162 return sz;
00163 }
00164
00165 ON_BrepEdge& ON_BrepEdge::operator=(const ON_BrepEdge& src)
00166 {
00167 if ( &src != this )
00168 {
00169
00170 ON_CurveProxy::operator=(src);
00171 m_edge_user = src.m_edge_user;
00172 m_edge_index = src.m_edge_index;
00173 m_c3i = src.m_c3i;
00174 m_vi[0] = src.m_vi[0];
00175 m_vi[1] = src.m_vi[1];
00176 m_ti = src.m_ti;
00177 m_tolerance = src.m_tolerance;
00178 }
00179 return *this;
00180 }
00181
00182 ON_BOOL32 ON_BrepEdge::IsValid( ON_TextLog* text_log ) const
00183 {
00184 bool rc = ON_CurveProxy::IsValid(text_log) ? true : false;
00185
00186 if ( !rc )
00187 {
00188 if ( text_log )
00189 {
00190 text_log->Print("ON_BrepEdge is not a valid curve proxy\n");
00191 }
00192 }
00193 else if (m_edge_index < 0)
00194 {
00195 if ( text_log )
00196 {
00197 text_log->Print("ON_BrepEdge.m_edge_index = %d (should be >= 0 )\n",m_edge_index);
00198 }
00199 rc = false;
00200 }
00201 else if ( m_c3i < 0 )
00202 {
00203 if ( text_log )
00204 {
00205 text_log->Print("ON_BrepEdge.m_c3i = %d (should be >= 0 )\n",m_c3i);
00206 }
00207 rc = false;
00208 }
00209 else if ( m_vi[0] < 0 )
00210 {
00211 if ( text_log )
00212 {
00213 text_log->Print("ON_BrepEdge.m_vi[0] = %d (should be >= 0 )\n",m_vi[0]);
00214 }
00215 rc = false;
00216 }
00217 else if ( m_vi[1] < 0 )
00218 {
00219 if ( text_log )
00220 {
00221 text_log->Print("ON_BrepEdge.m_vi[1] = %d (should be >= 0 )\n",m_vi[1]);
00222 }
00223 rc = false;
00224 }
00225 else if ( !m_brep )
00226 {
00227 if ( text_log )
00228 {
00229 text_log->Print("ON_BrepEdge.m_brep = NULL (should point to parent ON_Brep)\n");
00230 }
00231 rc = false;
00232 }
00233
00234 return rc;
00235
00236 }
00237
00238 ON_BOOL32 ON_BrepEdge::IsClosed() const
00239 {
00240
00241 ON_BOOL32 rc = ON_CurveProxy::IsClosed();
00242 if ( 0 == rc
00243 && m_vi[0] >= 0
00244 && m_vi[0] == m_vi[1]
00245 && 0 != ProxyCurve()
00246 && ProxyCurveDomain() == ProxyCurve()->Domain()
00247 && 0 != m_brep
00248 && m_vi[0] < m_brep->m_V.Count()
00249 )
00250 {
00251
00252
00253
00254 const ON_BrepVertex& v = m_brep->m_V[m_vi[0]];
00255 ON_3dPoint P = PointAtStart();
00256 ON_3dPoint Q = PointAtEnd();
00257 ON_3dPoint V = v.point;
00258 double vtx_tol = v.m_tolerance;
00259 if ( P.DistanceTo(Q) <= m_tolerance
00260 && V.DistanceTo(P) <= vtx_tol
00261 && V.DistanceTo(Q) <= vtx_tol )
00262 rc = true;
00263 }
00264 return rc;
00265 }
00266
00267 ON_Brep* ON_BrepEdge::Brep() const
00268 {
00269 return m_brep;
00270 }
00271
00272 ON_BrepTrim* ON_BrepEdge::Trim( int eti ) const
00273 {
00274 return (m_brep && eti >= 0 && eti < m_ti.Count()) ? m_brep->Trim(m_ti[eti]) : 0;
00275 }
00276
00277 int ON_BrepEdge::TrimCount() const
00278 {
00279 return m_ti.Count();
00280 }
00281
00282 void ON_BrepEdge::Dump( ON_TextLog& dump ) const
00283 {
00284 dump.Print("ON_BrepEdge[%d]: ",m_edge_index);
00285 }
00286
00287
00288
00289 ON_BOOL32 ON_BrepEdge::Reverse()
00290 {
00291 ON_BOOL32 rc = false;
00292 if ( m_brep )
00293 {
00294 ON_Interval edge_domain = Domain();
00295 if ( m_brep->StandardizeEdgeCurve( m_edge_index, false ) )
00296 {
00297 ON_Curve* c3 = const_cast<ON_Curve*>(EdgeCurveOf());
00298 if ( c3 )
00299 {
00300 rc = c3->Reverse();
00301 edge_domain.Reverse();
00302 c3->SetDomain(edge_domain);
00303 SetProxyCurve(c3);
00304 }
00305 }
00306 }
00307
00308 if ( !rc )
00309 rc = ON_CurveProxy::Reverse();
00310
00311 if (rc)
00312 {
00313 int i = m_vi[0];
00314 m_vi[0] = m_vi[1];
00315 m_vi[1] = i;
00316 if ( m_brep )
00317 {
00318 const int tcount = m_brep->m_T.Count();
00319 int ti, eti;
00320 for ( eti = m_ti.Count()-1; eti >= 0; eti-- ) {
00321 ti = m_ti[eti];
00322 if ( ti >= 0 && ti < tcount )
00323 {
00324 ON_BrepTrim& trim = m_brep->m_T[ti];
00325 trim.m_bRev3d = trim.m_bRev3d ? false : true;
00326 trim.UnsetPlineEdgeParameters();
00327 }
00328 }
00329 }
00330 }
00331
00332 return rc;
00333 }
00334
00336
00338
00339 ON_OBJECT_IMPLEMENT(ON_BrepTrim,ON_CurveProxy,"60B5DBC2-E660-11d3-BFE4-0010830122F0");
00340
00341 ON_BrepTrim::ON_BrepTrim()
00342 : m_trim_index(-1),
00343 m_c2i(-1),
00344 m_ei(-1),
00345 m_bRev3d(false),
00346 m_type(ON_BrepTrim::unknown),
00347 m_iso(ON_Surface::not_iso),
00348 m_li(-1),
00349 m__legacy_2d_tol(ON_UNSET_VALUE),
00350 m__legacy_3d_tol(ON_UNSET_VALUE),
00351 m__legacy_flags(0),
00352 m_brep(0)
00353 {
00354 memset(&m_trim_user,0,sizeof(m_trim_user));
00355 m_vi[0] = m_vi[1] = -1;
00356 m_tolerance[0] = m_tolerance[1] = ON_UNSET_VALUE;
00357 m_pline.Reserve(4);
00358
00359
00360
00361
00362 }
00363
00364 ON_BrepTrim::ON_BrepTrim(int trim_index)
00365 : m_trim_index(trim_index),
00366 m_c2i(-1),
00367 m_ei(-1),
00368 m_bRev3d(false),
00369 m_type(ON_BrepTrim::unknown),
00370 m_iso(ON_Surface::not_iso),
00371 m_li(-1),
00372 m__legacy_2d_tol(ON_UNSET_VALUE),
00373 m__legacy_3d_tol(ON_UNSET_VALUE),
00374 m__legacy_flags(0),
00375 m_brep(0)
00376 {
00377 memset(&m_trim_user,0,sizeof(m_trim_user));
00378 m_vi[0] = m_vi[1] = -1;
00379 m_tolerance[0] = m_tolerance[1] = ON_UNSET_VALUE;
00380 m_pline.Reserve(4);
00381
00382
00383
00384
00385 }
00386
00387
00388 unsigned int ON_BrepTrim::SizeOf() const
00389 {
00390 unsigned int sz = ON_CurveProxy::SizeOf();
00391 sz = (sizeof(*this) - sizeof(ON_CurveProxy));
00392
00393 return sz;
00394 }
00395
00396
00397 ON_BrepTrim& ON_BrepTrim::operator=(const ON_BrepTrim& src)
00398 {
00399 if ( &src != this )
00400 {
00401
00402 ON_CurveProxy::operator=(src);
00403 m_trim_user = src.m_trim_user;
00404 m_trim_index = src.m_trim_index;
00405 m_c2i = src.m_c2i;
00406
00407 m_ei = src.m_ei;
00408 m_vi[0] = src.m_vi[0];
00409 m_vi[1] = src.m_vi[1];
00410 m_bRev3d = src.m_bRev3d;
00411 m_type = src.m_type;
00412 m_iso = src.m_iso;
00413 m_li = src.m_li;
00414 m_tolerance[0] = src.m_tolerance[0];
00415 m_tolerance[1] = src.m_tolerance[1];
00416
00417
00418 m__legacy_2d_tol = src.m__legacy_2d_tol;
00419 m__legacy_3d_tol = src.m__legacy_3d_tol;
00420 m__legacy_flags = src.m__legacy_flags;
00421 m_pline = src.m_pline;
00422 m_pbox = src.m_pbox;
00423 }
00424 return *this;
00425 }
00426
00427 ON_Brep* ON_BrepTrim::Brep() const
00428 {
00429 return m_brep;
00430 }
00431
00432 ON_BrepLoop* ON_BrepTrim::Loop() const
00433 {
00434 ON_BrepLoop* loop = 0;
00435 if ( m_brep && m_li >= 0 && m_li < m_brep->m_L.Count() )
00436 loop = &m_brep->m_L[m_li];
00437 return loop;
00438 }
00439
00440 ON_BrepFace* ON_BrepTrim::Face() const
00441 {
00442 ON_BrepFace* face = 0;
00443 if ( m_brep && m_li >= 0 && m_li < m_brep->m_L.Count() )
00444 {
00445 int fi = m_brep->m_L[m_li].m_fi;
00446 if ( fi >= 0 && fi < m_brep->m_F.Count() )
00447 face = &m_brep->m_F[fi];
00448 }
00449 return face;
00450 }
00451
00452 ON_BrepEdge* ON_BrepTrim::Edge() const
00453 {
00454 ON_BrepEdge* edge = 0;
00455 if ( m_brep && m_ei >= 0 && m_ei < m_brep->m_E.Count() )
00456 edge = &m_brep->m_E[m_ei];
00457 return edge;
00458 }
00459
00460 ON_BrepVertex* ON_BrepTrim::Vertex(int tvi) const
00461 {
00462 ON_BrepVertex* vertex = 0;
00463 if ( 0 != m_brep && 0 <= tvi && tvi <= 1 )
00464 {
00465 int vi = m_vi[tvi];
00466 if ( 0 <= vi && vi < m_brep->m_V.Count() )
00467 {
00468 vertex = &m_brep->m_V[vi];
00469 }
00470 }
00471 return vertex;
00472 }
00473
00474 ON_BrepVertex* ON_BrepEdge::Vertex(int evi) const
00475 {
00476 ON_BrepVertex* vertex = 0;
00477 if ( 0 != m_brep && 0 <= evi && evi <= 1 )
00478 {
00479 int vi = m_vi[evi];
00480 if ( 0 <= vi && vi < m_brep->m_V.Count() )
00481 {
00482 vertex = &m_brep->m_V[vi];
00483 }
00484 }
00485 return vertex;
00486 }
00487
00488
00489 ON_BOOL32 ON_BrepTrim::IsValid( ON_TextLog* text_log ) const
00490 {
00491 if ( m_trim_index < 0 )
00492 {
00493 if ( text_log )
00494 {
00495 text_log->Print("trim.m_trim_index < 0.\n");
00496 }
00497 return ON_BrepIsNotValid();
00498 }
00499
00500 if ( m_c2i < 0 )
00501 {
00502 if ( text_log )
00503 {
00504 text_log->Print("trim.m_c2i = %d is not valid\n",m_c2i);
00505 }
00506 return ON_BrepIsNotValid();
00507 }
00508
00509 if ( !ON_CurveProxy::IsValid(text_log) )
00510 {
00511 if ( text_log )
00512 {
00513 text_log->Print("trim curve proxy settings are not valid.\n");
00514 }
00515 return ON_BrepIsNotValid();
00516 }
00517
00518 if ( m_ei < 0 )
00519 {
00520 if ( m_type != singular )
00521 {
00522 if ( text_log )
00523 {
00524 text_log->Print("trim.m_ei = %d but trim.mtype != singular\n",m_ei);
00525 }
00526 return ON_BrepIsNotValid();
00527 }
00528 }
00529
00530 if ( m_vi[0] < 0 )
00531 {
00532 if ( text_log )
00533 {
00534 text_log->Print("trim.m_v[0] = %d is not valid\n",m_vi[0]);
00535 }
00536 return ON_BrepIsNotValid();
00537 }
00538
00539 if ( m_vi[1] < 0 )
00540 {
00541 if ( text_log )
00542 {
00543 text_log->Print("trim.m_v[1] = %d is not valid\n",m_vi[1]);
00544 }
00545 return ON_BrepIsNotValid();
00546 }
00547
00548 unsigned int i = m_type;
00549 if ( i >= trim_type_count )
00550 {
00551 if ( text_log )
00552 {
00553 text_log->Print("trim.m_type = %d is not valid\n",i);
00554 }
00555 return ON_BrepIsNotValid();
00556 }
00557
00558 if ( i == ON_BrepTrim::slit )
00559 {
00560 if ( text_log )
00561 {
00562 text_log->Print("trim.m_type = ON_BrepTrim::slit is not valid. REserved for future use.\n",i);
00563 }
00564 return ON_BrepIsNotValid();
00565 }
00566
00567 i = m_iso;
00568 if ( i >= ON_Surface::iso_count )
00569 {
00570 if ( text_log )
00571 {
00572 text_log->Print("trim.m_iso = %d is not valid\n",i);
00573 }
00574 return ON_BrepIsNotValid();
00575 }
00576
00577 if ( m_li < 0 )
00578 {
00579 if ( text_log )
00580 {
00581 text_log->Print("trim.m_li = %d is not valid\n",m_li);
00582 }
00583 return ON_BrepIsNotValid();
00584 }
00585
00586 if ( !m_brep )
00587 {
00588 if ( text_log )
00589 {
00590 text_log->Print("trim.m_brep is null.\n");
00591 }
00592 return ON_BrepIsNotValid();
00593 }
00594
00595 return true;
00596 }
00597
00598 void ON_BrepTrim::Dump( ON_TextLog& dump ) const
00599 {
00600 dump.Print("ON_BrepTrim[%d]:\n",m_trim_index);
00601 }
00602
00603 ON_BOOL32 ON_BrepTrim::Reverse()
00604 {
00605 m_pline.Destroy();
00606 DestroyCurveTree();
00607
00608 ON_BOOL32 rc = false;
00609 if ( m_brep )
00610 {
00611 ON_Interval trim_domain = Domain();
00612 if ( m_brep->StandardizeTrimCurve( m_trim_index ) )
00613 {
00614 ON_Curve* c2 = const_cast<ON_Curve*>(TrimCurveOf());
00615 if ( c2 )
00616 {
00617 rc = c2->Reverse();
00618 trim_domain.Reverse();
00619 c2->SetDomain(trim_domain);
00620 SetProxyCurve(c2);
00621 }
00622 }
00623 }
00624
00625 if ( !rc )
00626 rc = ON_CurveProxy::Reverse();
00627
00628 if (rc)
00629 {
00630 int i = m_vi[0];
00631 m_vi[0] = m_vi[1];
00632 m_vi[1] = i;
00633 if ( m_ei >= 0 )
00634 m_bRev3d = m_bRev3d ? false : true;
00635 }
00636 return rc;
00637 }
00638
00639
00641
00643
00644 ON_OBJECT_IMPLEMENT(ON_BrepLoop,ON_Geometry,"60B5DBC3-E660-11d3-BFE4-0010830122F0");
00645
00646 ON_BrepLoop::ON_BrepLoop()
00647 : m_loop_index(-1),
00648 m_type(ON_BrepLoop::unknown),
00649 m_fi(-1),
00650 m_brep(0)
00651 {
00652 memset(&m_loop_user,0,sizeof(m_loop_user));
00653 }
00654
00655 ON_BrepLoop::ON_BrepLoop(int loop_index)
00656 : m_loop_index(loop_index),
00657 m_type(ON_BrepLoop::unknown),
00658 m_fi(-1),
00659 m_brep(0)
00660 {
00661 memset(&m_loop_user,0,sizeof(m_loop_user));
00662 }
00663
00664 ON_Brep* ON_BrepLoop::Brep() const
00665 {
00666 return m_brep;
00667 }
00668
00669 ON_BrepFace* ON_BrepLoop::Face() const
00670 {
00671 return m_brep ? m_brep->Face(m_fi) : 0;
00672 }
00673
00674
00675 unsigned int ON_BrepLoop::SizeOf() const
00676 {
00677 unsigned int sz = ON_Object::SizeOf();
00678 sz += (sizeof(ON_BrepLoop) - sizeof(ON_Object));
00679 sz += m_ti.SizeOfArray();
00680 return sz;
00681 }
00682
00683 ON_BrepTrim* ON_BrepLoop::Trim( int lti ) const
00684 {
00685 ON_BrepTrim* trim = ( m_brep && lti >= 0 && lti < m_ti.Count() )
00686 ? m_brep->Trim(m_ti[lti])
00687 : 0;
00688 return trim;
00689 }
00690
00691 int ON_BrepLoop::TrimCount() const
00692 {
00693 return m_ti.Count();
00694 }
00695
00696 ON_BrepLoop& ON_BrepLoop::operator=(const ON_BrepLoop& src)
00697 {
00698 if ( &src != this )
00699 {
00700
00701 ON_Object::operator=(src);
00702 m_loop_user = src.m_loop_user;
00703 m_loop_index = src.m_loop_index;
00704 m_ti = src.m_ti;
00705 m_type = src.m_type;
00706 m_fi = src.m_fi;
00707 m_pbox = src.m_pbox;
00708 }
00709 return *this;
00710 }
00711
00712 static void BadLoopMessage( int loop_index, ON_TextLog* text_log )
00713 {
00714 if ( text_log )
00715 {
00716 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
00717 }
00718 }
00719
00720 ON_BOOL32 ON_BrepLoop::IsValid( ON_TextLog* text_log ) const
00721 {
00722 if ( m_loop_index < 0 )
00723 {
00724 BadLoopMessage(m_loop_index,text_log);
00725 if ( text_log )
00726 text_log->Print("loop.m_loop_index < 0.\n");
00727 return ON_BrepIsNotValid();
00728 }
00729
00730 if ( m_ti.Count() < 1 )
00731 {
00732 BadLoopMessage(m_loop_index,text_log);
00733 if ( text_log )
00734 text_log->Print("loop.m_ti[] is empty.\n");
00735 return ON_BrepIsNotValid();
00736 }
00737 int i = m_type;
00738 if ( i < 0 || i > type_count )
00739 {
00740 BadLoopMessage(m_loop_index,text_log);
00741 if ( text_log )
00742 text_log->Print("loop.m_type = %d is not a valid value.\n",i);
00743 return ON_BrepIsNotValid();
00744 }
00745 if ( m_fi < 0 )
00746 {
00747 BadLoopMessage(m_loop_index,text_log);
00748 if ( text_log )
00749 text_log->Print("loop.m_fi = %d (should be >= 0 ).\n",m_fi);
00750 return ON_BrepIsNotValid();
00751 }
00752 if ( !m_brep )
00753 {
00754 BadLoopMessage(m_loop_index,text_log);
00755 if ( text_log )
00756 text_log->Print("loop.m_brep is NULL.\n");
00757 return ON_BrepIsNotValid();
00758 }
00759 return true;
00760 }
00761
00762 void ON_BrepLoop::Dump( ON_TextLog& dump ) const
00763 {
00764 dump.Print("ON_BrepLoop[%d]: m_fi = %d, m_type = %d m_ti.Count() = %d\n",
00765 m_loop_index,m_fi,m_type,m_ti.Count()
00766 );
00767 }
00768
00769 int ON_BrepLoop::IndexOfTrim( const ON_BrepTrim& trim ) const
00770 {
00771 const int count = m_ti.Count();
00772 int lti;
00773 for ( lti = 0; lti < count; lti++ )
00774 {
00775 if ( m_ti[lti] == trim.m_trim_index )
00776 return lti;
00777 }
00778 return -1;
00779 }
00780
00782
00784
00785 ON_OBJECT_IMPLEMENT(ON_BrepFace,ON_SurfaceProxy,"60B5DBC4-E660-11d3-BFE4-0010830122F0");
00786
00787 ON_BrepFace::ON_BrepFace() : ON_SurfaceProxy(0),
00788 m_face_index(-1),
00789 m_si(-1),
00790 m_bRev(false),
00791 m_face_material_channel(0),
00792 m_render_mesh(0),
00793 m_analysis_mesh(0),
00794 m_preview_mesh(0),
00795 m_brep(0)
00796 {
00797 m_face_uuid = ON_nil_uuid;
00798 memset(&m_face_user,0,sizeof(m_face_user));
00799 }
00800
00801 ON_BrepFace::ON_BrepFace(int face_index) : ON_SurfaceProxy(0),
00802 m_face_index(face_index),
00803 m_si(-1),
00804 m_bRev(false),
00805 m_face_material_channel(0),
00806 m_render_mesh(0),
00807 m_analysis_mesh(0),
00808 m_preview_mesh(0),
00809 m_brep(0)
00810 {
00811 m_face_uuid = ON_nil_uuid;
00812 memset(&m_face_user,0,sizeof(m_face_user));
00813 }
00814
00815
00816 unsigned int ON_BrepFace::SizeOf() const
00817 {
00818 unsigned int sz = ON_SurfaceProxy::SizeOf();
00819 sz += (sizeof(*this) - sizeof(ON_SurfaceProxy));
00820 sz += m_li.SizeOfArray();
00821 if ( m_render_mesh )
00822 sz += m_render_mesh->SizeOf();
00823 if ( m_analysis_mesh )
00824 sz += m_analysis_mesh->SizeOf();
00825 if ( m_preview_mesh )
00826 sz += m_preview_mesh->SizeOf();
00827 return sz;
00828 }
00829
00830
00831 ON_BrepFace& ON_BrepFace::operator=(const ON_BrepFace& src)
00832 {
00833 if ( &src != this )
00834 {
00835
00836 ON_SurfaceProxy::operator=(src);
00837 m_face_user = src.m_face_user;
00838 m_face_index = src.m_face_index;
00839 m_li = src.m_li;
00840 m_si = src.m_si;
00841 m_bRev = src.m_bRev;
00842 m_face_material_channel = src.m_face_material_channel;
00843 m_face_uuid = src.m_face_uuid;
00844 if ( m_render_mesh ) {
00845 delete m_render_mesh;
00846 m_render_mesh = 0;
00847 }
00848 if ( src.m_render_mesh ) {
00849 m_render_mesh = new ON_Mesh(*src.m_render_mesh);
00850 }
00851 if ( m_analysis_mesh ) {
00852 delete m_analysis_mesh;
00853 m_analysis_mesh = 0;
00854 }
00855 if ( src.m_analysis_mesh ) {
00856 m_analysis_mesh = new ON_Mesh(*src.m_analysis_mesh);
00857 }
00858 if ( m_preview_mesh ) {
00859 delete m_preview_mesh;
00860 m_preview_mesh = 0;
00861 }
00862 if ( src.m_preview_mesh ) {
00863 m_preview_mesh = new ON_Mesh(*src.m_preview_mesh);
00864 }
00865
00866 }
00867 return *this;
00868 }
00869
00870 ON_BrepFace::~ON_BrepFace()
00871 {
00872 DestroyMesh(ON::any_mesh);
00873 m_li.Destroy();
00874 }
00875
00876 ON_Brep* ON_BrepFace::Brep() const
00877 {
00878 return m_brep;
00879 }
00880
00881 ON_BrepLoop* ON_BrepFace::Loop( int lti ) const
00882 {
00883 return (m_brep && lti >= 0 && lti < m_li.Count()) ? m_brep->Loop( m_li[lti]) : 0;
00884 }
00885
00886 int ON_BrepFace::LoopCount() const
00887 {
00888 return m_li.Count();
00889 }
00890
00891 ON_BrepLoop* ON_BrepFace::OuterLoop() const
00892 {
00893 int li, lti;
00894 for ( lti = 0; lti < m_li.Count(); lti++ )
00895 {
00896 li = m_li[lti];
00897 if ( li >= 0 && li < m_brep->m_L.Count() )
00898 {
00899 if ( ON_BrepLoop::outer == m_brep->m_L[li].m_type )
00900 {
00901 return &m_brep->m_L[li];
00902 }
00903 }
00904 }
00905 return 0;
00906 }
00907
00908
00909 ON_BOOL32 ON_BrepFace::IsValid( ON_TextLog* text_log ) const
00910 {
00911 if ( m_face_index < 0 )
00912 {
00913 if ( 0 != text_log )
00914 text_log->Print("ON_BrepFace m_face_index = %d. Should be >= 0.\n",m_face_index);
00915 return false;
00916 }
00917
00918 if ( m_li.Count() < 1 )
00919 {
00920 if ( 0 != text_log )
00921 text_log->Print("ON_BrepFace m_li.Count() = 0 Should be > 0.\n");
00922 return false;
00923 }
00924
00925 if ( m_si < 0 )
00926 {
00927 if ( 0 != text_log )
00928 text_log->Print("ON_BrepFace m_si = %d. Should be >= 0.\n",m_si);
00929 return false;
00930 }
00931
00932 if ( 0 == m_brep )
00933 {
00934 if ( 0 != text_log )
00935 text_log->Print("ON_BrepFace m_brep = 0. Should point to parent brep.\n");
00936 return false;
00937
00938 }
00939
00940 return true;
00941 }
00942
00943 void ON_BrepFace::Dump( ON_TextLog& dump ) const
00944 {
00945 dump.Print("ON_BrepFace[%d]:",m_face_index);
00946 if ( ON_UuidCompare(m_face_uuid,ON_nil_uuid) )
00947 {
00948 dump.Print(" (");
00949 dump.Print(m_face_uuid);
00950 dump.Print(" )");
00951 }
00952 dump.Print("\n");
00953 }
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 const ON_Mesh* ON_BrepFace::Mesh( ON::mesh_type mt ) const
00969 {
00970 ON_Mesh* m = 0;
00971 switch(mt) {
00972 case ON::render_mesh:
00973 m = m_render_mesh;
00974 break;
00975 case ON::analysis_mesh:
00976 m = m_analysis_mesh;
00977 break;
00978 case ON::preview_mesh:
00979 m = m_preview_mesh;
00980 break;
00981 default:
00982 m = m_render_mesh ? m_render_mesh : m_analysis_mesh;
00983 if ( !m )
00984 m = m_preview_mesh;
00985 break;
00986 }
00987 if ( m ) {
00988 m->m_parent = this;
00989
00990 }
00991 return m;
00992 }
00993
00994 void ON_BrepFace::DestroyMesh( ON::mesh_type mt, bool bDeleteMesh )
00995 {
00996 switch(mt) {
00997 case ON::render_mesh:
00998 if ( m_render_mesh )
00999 {
01000 if ( bDeleteMesh )
01001 delete m_render_mesh;
01002 m_render_mesh = 0;
01003 }
01004 break;
01005 case ON::analysis_mesh:
01006 if (m_analysis_mesh)
01007 {
01008 if ( bDeleteMesh )
01009 delete m_analysis_mesh;
01010 m_analysis_mesh = 0;
01011 }
01012 break;
01013 case ON::preview_mesh:
01014 if (m_preview_mesh)
01015 {
01016 if ( bDeleteMesh )
01017 delete m_preview_mesh;
01018 m_preview_mesh = 0;
01019 }
01020 break;
01021 default:
01022 DestroyMesh( ON::render_mesh );
01023 DestroyMesh( ON::analysis_mesh );
01024 DestroyMesh( ON::preview_mesh );
01025 break;
01026 }
01027 }
01028
01029
01030 unsigned int ON_BrepVertexArray::SizeOf() const
01031 {
01032 unsigned int sz = 0;
01033 int i, count = Count();
01034 for ( i = 0; i < count; i++ )
01035 {
01036 sz += m_a[i].SizeOf();
01037 }
01038 sz += (m_capacity - m_count)*sizeof(m_a[0]);
01039 return sz;
01040 }
01041
01042 unsigned int ON_BrepEdgeArray::SizeOf() const
01043 {
01044 unsigned int sz = 0;
01045 int i, count = Count();
01046 for ( i = 0; i < count; i++ )
01047 {
01048 sz += m_a[i].SizeOf();
01049 }
01050 sz += (m_capacity - m_count)*sizeof(m_a[0]);
01051 return sz;
01052 }
01053
01054 unsigned int ON_BrepTrimArray::SizeOf() const
01055 {
01056 unsigned int sz = 0;
01057 int i, count = Count();
01058 for ( i = 0; i < count; i++ )
01059 {
01060 sz += m_a[i].SizeOf();
01061 }
01062 sz += (m_capacity - m_count)*sizeof(m_a[0]);
01063 return sz;
01064 }
01065
01066 unsigned int ON_BrepLoopArray::SizeOf() const
01067 {
01068 unsigned int sz = 0;
01069 int i, count = Count();
01070 for ( i = 0; i < count; i++ )
01071 {
01072 sz += m_a[i].SizeOf();
01073 }
01074 sz += (m_capacity - m_count)*sizeof(m_a[0]);
01075 return sz;
01076 }
01077
01078 unsigned int ON_BrepFaceArray::SizeOf() const
01079 {
01080 unsigned int sz = 0;
01081 int i, count = Count();
01082 for ( i = 0; i < count; i++ )
01083 {
01084 sz += m_a[i].SizeOf();
01085 }
01086 sz += (m_capacity - m_count)*sizeof(m_a[0]);
01087 return sz;
01088 }
01089
01091
01093
01094 ON_BrepVertexArray::ON_BrepVertexArray()
01095 {}
01096
01097 ON_BrepVertexArray::~ON_BrepVertexArray()
01098 {}
01099
01100
01101 ON_BrepEdgeArray::ON_BrepEdgeArray()
01102 {}
01103
01104 ON_BrepEdgeArray::~ON_BrepEdgeArray()
01105 {}
01106
01107
01108 ON_BrepTrimArray::ON_BrepTrimArray()
01109 {}
01110
01111 ON_BrepTrimArray::~ON_BrepTrimArray()
01112 {}
01113
01114
01115 ON_BrepLoopArray::ON_BrepLoopArray()
01116 {}
01117
01118 ON_BrepLoopArray::~ON_BrepLoopArray()
01119 {}
01120
01121 ON_BrepFaceArray::ON_BrepFaceArray()
01122 {}
01123
01124 ON_BrepFaceArray::~ON_BrepFaceArray()
01125 {}
01126
01127
01128 ON_OBJECT_IMPLEMENT(ON_Brep,ON_Geometry,"60B5DBC5-E660-11d3-BFE4-0010830122F0");
01129
01130 void ON_Brep::Initialize()
01131 {
01132 memset(&m_brep_user,0,sizeof(m_brep_user));
01133 m_is_solid = 0;
01134 m_bbox.Destroy();
01135 }
01136
01137 ON_Brep* ON_Brep::New()
01138 {
01139
01140
01141
01142 return new ON_Brep();
01143 }
01144
01145 ON_Brep* ON_Brep::New(const ON_Brep& src)
01146 {
01147
01148
01149
01150 return new ON_Brep(src);
01151 }
01152
01153 ON_Brep::ON_Brep()
01154 {
01155 ON__SET__THIS__PTR(m_s_ON_Brep_ptr);
01156 Initialize();
01157 }
01158
01159 ON_Brep::ON_Brep(const ON_Brep& src) : ON_Geometry(src)
01160 {
01161 ON__SET__THIS__PTR(m_s_ON_Brep_ptr);
01162 Initialize();
01163 *this = src;
01164 }
01165
01166 ON_Brep::~ON_Brep()
01167 {
01168 DestroyMesh(ON::any_mesh,true);
01169
01170 }
01171
01172 unsigned int ON_Brep::SizeOf() const
01173 {
01174 int i, count;
01175
01176 unsigned int sz = ON_Geometry::SizeOf();
01177 sz += (sizeof(*this) - sizeof(ON_Geometry));
01178 sz += m_C2.SizeOfArray();
01179 sz += m_C3.SizeOfArray();
01180 sz += m_S.SizeOfArray();
01181
01182 count = m_C2.Count();
01183 for ( i = 0; i < count; i++ )
01184 {
01185 const ON_Curve* c2 = m_C2[i];
01186 if ( c2 )
01187 sz += c2->SizeOf();
01188 }
01189
01190 count = m_C3.Count();
01191 for ( i = 0; i < count; i++ )
01192 {
01193 const ON_Curve* c3 = m_C3[i];
01194 if ( c3 )
01195 sz += c3->SizeOf();
01196 }
01197
01198 count = m_S.Count();
01199 for ( i = 0; i < count; i++ )
01200 {
01201 const ON_Surface* s = m_S[i];
01202 if ( s )
01203 sz += s->SizeOf();
01204 }
01205
01206 sz += m_V.SizeOf();
01207 sz += m_E.SizeOf();
01208 sz += m_T.SizeOf();
01209 sz += m_L.SizeOf();
01210 sz += m_F.SizeOf();
01211
01212 return sz;
01213 }
01214
01215 ON__UINT32 ON_BrepVertex::DataCRC(ON__UINT32 current_remainder) const
01216 {
01217 current_remainder = ON_CRC32(current_remainder,sizeof(m_vertex_index),&m_vertex_index);
01218 current_remainder = ON_CRC32(current_remainder,sizeof(m_tolerance),&m_tolerance);
01219 current_remainder = m_ei.DataCRC(current_remainder);
01220 return current_remainder;
01221 }
01222
01223 ON__UINT32 ON_BrepEdge::DataCRC(ON__UINT32 current_remainder) const
01224 {
01225 current_remainder = ON_CurveProxy::DataCRC(current_remainder);
01226 current_remainder = ON_CRC32(current_remainder,sizeof(m_edge_index),&m_edge_index);
01227 current_remainder = ON_CRC32(current_remainder,sizeof(m_c3i),&m_c3i);
01228 current_remainder = ON_CRC32(current_remainder,2*sizeof(m_vi[0]),&m_vi[0]);
01229 current_remainder = m_ti.DataCRC(current_remainder);
01230 current_remainder = ON_CRC32(current_remainder,sizeof(m_tolerance),&m_tolerance);
01231
01232 return current_remainder;
01233 }
01234
01235 ON__UINT32 ON_BrepFace::DataCRC(ON__UINT32 current_remainder) const
01236 {
01237 current_remainder = ON_SurfaceProxy::DataCRC(current_remainder);
01238 current_remainder = ON_CRC32(current_remainder,sizeof(m_face_index),&m_face_index);
01239 current_remainder = ON_CRC32(current_remainder,sizeof(m_bRev),&m_bRev);
01240 current_remainder = m_li.DataCRC(current_remainder);
01241
01242 return current_remainder;
01243 }
01244
01245 ON__UINT32 ON_Brep::DataCRC(ON__UINT32 current_remainder) const
01246 {
01247 current_remainder = m_V.DataCRC(current_remainder);
01248 current_remainder = m_E.DataCRC(current_remainder);
01249 current_remainder = m_F.DataCRC(current_remainder);
01250 return current_remainder;
01251 }
01252
01253 void ON_Brep::DestroyMesh( ON::mesh_type mt, bool bDeleteMesh )
01254 {
01255 const int fcnt = m_F.Count();
01256 int fi;
01257 for ( fi = 0; fi < fcnt; fi++ ) {
01258 m_F[fi].DestroyMesh(mt,bDeleteMesh);
01259 }
01260 }
01261
01262 int ON_Brep::GetMesh( ON::mesh_type mt, ON_SimpleArray<const ON_Mesh*>& meshes ) const
01263 {
01264 int fcnt = m_F.Count();
01265 int fi;
01266 int null_count = 0;
01267 meshes.Reserve( meshes.Count() + fcnt );
01268 for ( fi = 0; fi < fcnt; fi++ )
01269 {
01270 const ON_Mesh* mesh = m_F[fi].Mesh(mt);
01271 meshes.Append( mesh );
01272 if ( !mesh )
01273 {
01274
01275
01276
01277 null_count++;
01278 }
01279 }
01280 if ( null_count == fcnt )
01281 {
01282
01283 meshes.SetCount(meshes.Count()-fcnt);
01284 fcnt = 0;
01285 }
01286 return fcnt;
01287 }
01288
01289
01290 int ON_Brep::Dimension() const
01291 {
01292 return (m_V.Count() > 0) ? 3 : 0;
01293 }
01294
01295 static void ON_BrepTransformSwapSrfHelper( ON_Brep& brep, ON_NurbsSurface* nurbs_srf, int si )
01296 {
01297
01298
01299 ON_Surface* old_srf = brep.m_S[si];
01300 ON_UserDataHolder udholder;
01301 udholder.MoveUserDataFrom(*old_srf);
01302 udholder.MoveUserDataTo(*nurbs_srf,false);
01303 brep.m_S[si] = nurbs_srf;
01304
01305
01306 const int fcount = brep.m_F.Count();
01307 ON_BrepFace* f = brep.m_F.Array();
01308 for ( int fi = 0; fi < fcount; fi++ )
01309 {
01310 if (f[fi].m_si == si || f[fi].ProxySurface() == old_srf )
01311 {
01312 const bool bIsTransposed = f[fi].ProxySurfaceIsTransposed();
01313 f[fi].SetProxySurface(nurbs_srf);
01314 if (bIsTransposed)
01315 f[fi].ON_SurfaceProxy::Transpose();
01316 }
01317 }
01318
01319 delete old_srf;
01320 }
01321
01322 ON_BOOL32 ON_Brep::Transform( const ON_Xform& xform )
01323 {
01324 int i, count;
01325 ON_BOOL32 rc = true;
01326
01327 DestroyRuntimeCache();
01328
01329 int is_similarity = xform.IsSimilarity();
01330 double det = xform.Determinant();
01331
01332 if ( 1 != is_similarity )
01333 {
01334
01335
01336 m_is_solid = 0;
01337 }
01338
01339
01340
01341
01342
01343
01344 m_bbox.Destroy();
01345
01346 count = m_C3.Count();
01347 for ( i = 0; i < count; i++ )
01348 {
01349 if ( m_C3[i] )
01350 {
01351 if ( !m_C3[i]->Transform(xform) )
01352 rc = false;
01353 }
01354 }
01355
01356 count = m_S.Count();
01357 for ( i = 0; i < count; i++ ) {
01358 if ( m_S[i] )
01359
01360 {
01361 ON_NurbsSurface* nurbs_srf = 0;
01362 if ( !is_similarity )
01363 {
01364 if ( 1 == m_S[i]->Degree(0)
01365 && 1 == m_S[i]->Degree(1)
01366 && 0 != ON_PlaneSurface::Cast(m_S[i]) )
01367 {
01368 nurbs_srf = ON_NurbsSurface::New();
01369 if ( !m_S[i]->GetNurbForm(*nurbs_srf) )
01370 {
01371 delete nurbs_srf;
01372 nurbs_srf = 0;
01373 }
01374 else if ( !nurbs_srf->Transform(xform) )
01375 {
01376 delete nurbs_srf;
01377 nurbs_srf = 0;
01378 }
01379 }
01380 }
01381
01382 if ( !m_S[i]->Transform(xform) )
01383 {
01384 if ( nurbs_srf )
01385 {
01386 ON_BrepTransformSwapSrfHelper(*this,nurbs_srf,i);
01387 nurbs_srf = 0;
01388 }
01389 else
01390 {
01391 rc = false;
01392 }
01393 }
01394 else if ( nurbs_srf )
01395 {
01396
01397 ON_Interval u = nurbs_srf->Domain(0);
01398 ON_Interval v = nurbs_srf->Domain(1);
01399 for ( int ui = 0; ui < 2 && nurbs_srf; ui++ ) for (int vi = 0; vi < 2 && nurbs_srf; vi++)
01400 {
01401 ON_3dPoint P = nurbs_srf->PointAt(u[ui],v[vi]);
01402 ON_3dPoint Q = m_S[i]->PointAt(u[ui],v[vi]);
01403 if ( P.DistanceTo(Q) > ON_ZERO_TOLERANCE )
01404 {
01405 ON_BrepTransformSwapSrfHelper(*this,nurbs_srf,i);
01406 nurbs_srf = 0;
01407 break;
01408 }
01409 }
01410 if ( nurbs_srf )
01411 {
01412 delete nurbs_srf;
01413 nurbs_srf = 0;
01414 }
01415 }
01416 }
01417 }
01418
01419 count = m_V.Count();
01420 for ( i = 0; i < count; i++ ) {
01421 if ( !m_V[i].Transform(xform) )
01422 rc = false;
01423 }
01424
01425 count = m_E.Count();
01426 for ( i = 0; i < count; i++ ) {
01427 m_E[i].TransformUserData(xform);
01428 }
01429
01430 count = m_F.Count();
01431 for ( i = 0; i < count; i++ )
01432 {
01433 ON_BrepFace& face = m_F[i];
01434 face.TransformUserData(xform);
01435
01436
01437
01438
01439 face.m_bbox.Destroy();
01440 const ON_Surface* srf = face.SurfaceOf();
01441 if ( 0 != srf )
01442 {
01443 face.m_bbox = srf->BoundingBox();
01444 if ( face.m_face_index != -1 )
01445 m_bbox.Union( face.m_bbox );
01446 }
01447
01448
01449
01450
01451
01452
01453 bool bEvMesh = ( fabs(det) <= ON_SQRT_EPSILON
01454 || xform[3][0] != 0.0
01455 || xform[3][1] != 0.0
01456 || xform[3][2] != 0.0
01457 || xform[3][3] != 1.0
01458 );
01459 if ( 0 == srf )
01460 bEvMesh = false;
01461
01462 if ( 0 != face.m_render_mesh )
01463 {
01464 if ( bEvMesh && face.m_render_mesh->EvaluateMeshGeometry(*srf) )
01465 {
01466 if ( face.m_bRev )
01467 {
01468
01469
01470
01471
01472
01473
01474 int ni, ncnt = face.m_render_mesh->m_N.Count();
01475 for ( ni = 0; ni < ncnt; ni++ )
01476 {
01477 face.m_render_mesh->m_N[ni].Reverse();
01478 }
01479 }
01480 }
01481 else
01482 face.m_render_mesh->Transform(xform);
01483 }
01484
01485 if ( 0 != face.m_analysis_mesh )
01486 {
01487
01488
01489
01490 bool bEvAnalysisMesh = bEvMesh;
01491 if ( !bEvAnalysisMesh )
01492 {
01493 ON_Xform tmp(xform);
01494 tmp.m_xform[0][3] = 0.0;
01495 tmp.m_xform[1][3] = 0.0;
01496 tmp.m_xform[2][3] = 0.0;
01497 if ( 1 != tmp.IsSimilarity() )
01498 bEvAnalysisMesh = true;
01499 }
01500 if ( !bEvAnalysisMesh || !face.m_analysis_mesh->EvaluateMeshGeometry(*srf) )
01501 face.m_analysis_mesh->Transform(xform);
01502 }
01503
01504 if ( 0 != face.m_preview_mesh )
01505 {
01506 if ( !bEvMesh || !face.m_preview_mesh->EvaluateMeshGeometry(*srf) )
01507 face.m_preview_mesh->Transform(xform);
01508 }
01509 }
01510
01511
01512
01513
01514
01515 TransformUserData(xform);
01516
01517 return rc;
01518 }
01519
01521
01522
01523 int
01524 ON_Brep::AddTrimCurve( ON_Curve* pC )
01525 {
01526 int c2i = -1;
01527
01528 if ( 0 != pC )
01529 {
01530
01531
01532
01533
01534
01535
01536 int dim = pC->Dimension();
01537
01538 if ( dim != 2 )
01539 {
01540 ON_ERROR("ON_Brep::AddTrimCurve() go a non-2d curve - changing dim to 2.");
01541 pC->ChangeDimension(2);
01542 dim = pC->Dimension();
01543 }
01544
01545 if ( 2 == dim )
01546 {
01547 c2i = m_C2.Count();
01548 m_C2.Append(pC);
01549 }
01550 }
01551 return c2i;
01552 }
01553
01554 int
01555 ON_Brep::AddEdgeCurve( ON_Curve* pC )
01556 {
01557 int c3i = -1;
01558 if ( 0 != pC )
01559 {
01560
01561 int dim = pC->Dimension();
01562
01563 if ( dim != 3 )
01564 {
01565
01566 ON_ERROR("ON_Brep::AddEdgeCurve() got a non-3d curve - changing dim to 3.");
01567 pC->ChangeDimension(3);
01568 dim = pC->Dimension();
01569 }
01570
01571 if ( 3 == dim )
01572 {
01573 c3i = m_C3.Count();
01574 m_C3.Append(pC);
01575 }
01576 }
01577 return c3i;
01578 }
01579
01580 int
01581 ON_Brep::AddSurface( ON_Surface* pS )
01582 {
01583 int si = -1;
01584 if ( pS && pS->Dimension() == 3 )
01585 {
01586 si = m_S.Count();
01587 m_S.Append(pS);
01588 }
01589 m_bbox.Destroy();
01590 m_is_solid = 0;
01591 return si;
01592 }
01593
01594 ON_BrepVertex&
01595 ON_Brep::NewVertex()
01596 {
01597 int vi = m_V.Count();
01598 m_V.Reserve(vi+1);
01599 m_V.SetCount(vi+1);
01600 ON_BrepVertex& vertex = m_V.Array()[vi];
01601 vertex.m_vertex_index = vi;
01602 vertex.point = ON_UNSET_POINT;
01603 vertex.m_tolerance = ON_UNSET_VALUE;
01604 return vertex;
01605 }
01606
01607 ON_BrepVertex&
01608 ON_Brep::NewVertex( ON_3dPoint vertex_point, double vertex_tolerance )
01609 {
01610 ON_BrepVertex& vertex = NewVertex();
01611 vertex.point = vertex_point;
01612 vertex.m_tolerance = vertex_tolerance;
01613 return vertex;
01614 }
01615
01616 ON_BrepEdge&
01617 ON_Brep::NewEdge( int c3i )
01618 {
01619 int ei = m_E.Count();
01620 ON_BrepEdge& edge = m_E.AppendNew();
01621 edge.m_tolerance = ON_UNSET_VALUE;
01622 edge.m_edge_index = ei;
01623 edge.m_c3i = c3i;
01624 if ( edge.m_c3i >= 0 && edge.m_c3i < m_C3.Count() )
01625 {
01626 edge.SetProxyCurve(m_C3[edge.m_c3i]);
01627 }
01628 edge.m_brep = this;
01629 return edge;
01630 }
01631
01632 ON_BrepEdge&
01633 ON_Brep::NewEdge( ON_BrepVertex& v0, ON_BrepVertex& v1,
01634 int c3i, const ON_Interval* edomain,
01635 double edge_tolerance )
01636 {
01637 ON_BrepEdge& edge = NewEdge(c3i);
01638 edge.m_vi[0] = v0.m_vertex_index;
01639 edge.m_vi[1] = v1.m_vertex_index;
01640 v0.m_ei.Append(edge.m_edge_index);
01641 v1.m_ei.Append(edge.m_edge_index);
01642 if ( edomain && edomain->IsIncreasing() ) {
01643 ON_Interval edom;
01644 edom.Intersection( edge.ProxyCurveDomain(), *edomain );
01645 if ( edom.IsIncreasing() )
01646 edge.SetProxyCurveDomain(edom);
01647 }
01648 edge.m_tolerance = edge_tolerance;
01649 return edge;
01650 }
01651
01652 bool ON_Brep::SetEdgeCurve(
01653 ON_BrepEdge& edge,
01654 int c3_index,
01655 const ON_Interval* sub_domain
01656 )
01657 {
01658 bool rc = false;
01659 if ( c3_index == - 1 && !sub_domain )
01660 {
01661 edge.m_c3i = -1;
01662 edge.SetProxyCurve(0);
01663 rc = true;
01664 }
01665 else if ( c3_index >= 0 && c3_index <= m_C3.Count() && m_C3[c3_index] )
01666 {
01667 ON_Interval curve_domain = m_C3[c3_index]->Domain();
01668 if ( !sub_domain || (sub_domain->IsIncreasing() && curve_domain.Includes(*sub_domain)) )
01669 {
01670 edge.m_c3i = c3_index;
01671 edge.SetProxyCurve( m_C3[c3_index],
01672 (sub_domain) ? *sub_domain : curve_domain
01673 );
01674 rc = true;
01675 }
01676 }
01677 return rc;
01678 }
01679
01680 bool ON_Brep::SetTrimCurve(
01681 ON_BrepTrim& trim,
01682 int c2_index,
01683 const ON_Interval* sub_domain
01684 )
01685 {
01686 bool rc = false;
01687 if ( c2_index == - 1 && !sub_domain )
01688 {
01689 trim.m_c2i = -1;
01690 trim.SetProxyCurve(0);
01691 rc = true;
01692 }
01693 else if ( c2_index >= 0 && c2_index <= m_C2.Count() && m_C2[c2_index] )
01694 {
01695 ON_Interval curve_domain = m_C2[c2_index]->Domain();
01696 if ( !sub_domain || (sub_domain->IsIncreasing() && curve_domain.Includes(*sub_domain)) )
01697 {
01698 trim.m_c2i = c2_index;
01699 trim.SetProxyCurve( m_C2[trim.m_c2i], (sub_domain) ? *sub_domain : curve_domain );
01700 trim.m_pbox = m_C2[trim.m_c2i]->BoundingBox();
01701 trim.m_pbox.m_min.z = 0.0;
01702 trim.m_pbox.m_max.z = 0.0;
01703 rc = true;
01704 }
01705 }
01706 return rc;
01707 }
01708
01709 ON_BrepTrim&
01710 ON_Brep::NewTrim( int c2i )
01711 {
01712 m_is_solid = 0;
01713 int ti = m_T.Count();
01714 ON_BrepTrim& trim = m_T.AppendNew();
01715 trim.m_brep = this;
01716 trim.m_trim_index = ti;
01717 trim.m_ei = -1;
01718 trim.m_type = ON_BrepTrim::unknown;
01719 trim.m_bRev3d = false;
01720 trim.m_c2i = c2i;
01721 trim.m_iso = ON_Surface::not_iso;
01722 trim.m_li = -1;
01723 trim.m_tolerance[0] = ON_UNSET_VALUE;
01724 trim.m_tolerance[1] = ON_UNSET_VALUE;
01725 trim.m__legacy_2d_tol = ON_UNSET_VALUE;
01726 trim.m__legacy_3d_tol = ON_UNSET_VALUE;
01727 trim.m__legacy_flags = 0;
01728 const ON_Curve* c2 = (c2i >= 0 && c2i < m_C2.Count())
01729 ? m_C2[c2i]
01730 : 0;
01731 if ( c2 )
01732 {
01733 trim.SetProxyCurve( c2 );
01734 trim.m_pbox = c2->BoundingBox();
01735 trim.m_pbox.m_min.z = 0.0;
01736 trim.m_pbox.m_max.z = 0.0;
01737 }
01738
01739 return trim;
01740 }
01741
01742 ON_BrepTrim&
01743 ON_Brep::NewTrim( ON_BrepEdge& edge, ON_BOOL32 bRev3d, int c2i )
01744 {
01745 m_is_solid = 0;
01746 ON_BrepTrim& trim = NewTrim( c2i );
01747 trim.m_ei = edge.m_edge_index;
01748 edge.m_ti.Append(trim.m_trim_index);
01749 trim.m_vi[0] = edge.m_vi[bRev3d?1:0];
01750 trim.m_vi[1] = edge.m_vi[bRev3d?0:1];
01751 trim.m_bRev3d = bRev3d?true:false;
01752 return trim;
01753 }
01754
01755
01756 ON_BrepTrim&
01757 ON_Brep::NewTrim( ON_BrepEdge& edge, ON_BOOL32 bRev3d, ON_BrepLoop& loop, int c2i )
01758 {
01759 m_is_solid = 0;
01760 const int edge_trim_count0 = edge.m_ti.Count();
01761 ON_BrepTrim& trim = NewTrim( edge, bRev3d, c2i );
01762 trim.m_li = loop.m_loop_index;
01763 loop.m_ti.Append(trim.m_trim_index);
01764 if ( c2i >= 0 && c2i < m_C2.Count() )
01765 {
01766 ON_Curve* c2 = m_C2[c2i];
01767 if ( c2 )
01768 {
01769 ON_BoundingBox c2_bbox;
01770 if ( c2->GetBoundingBox(c2_bbox) )
01771 {
01772 c2_bbox.m_min.z = 0.0;
01773 c2_bbox.m_max.z = 0.0;
01774 if ( loop.m_ti.Count() == 1 )
01775 loop.m_pbox = c2_bbox;
01776 else
01777 loop.m_pbox.Union(c2_bbox);
01778 }
01779 }
01780 }
01781
01782 if ( edge_trim_count0 == 0 )
01783 {
01784
01785
01786
01787
01788
01789 trim.m_type = ON_BrepTrim::boundary;
01790 }
01791 else if ( edge_trim_count0 == 1 )
01792 {
01793
01794 ON_BrepTrim::TYPE trim_type = ON_BrepTrim::mated;
01795 ON_BrepTrim& other_trim = m_T[edge.m_ti[0]];
01796 if ( other_trim.m_li == loop.m_loop_index )
01797 trim_type = ON_BrepTrim::seam;
01798 else
01799 trim_type = ON_BrepTrim::mated;
01800 trim.m_type = trim_type;
01801 other_trim.m_type = trim_type;
01802 }
01803 else
01804 {
01805
01806 ON_BrepTrim::TYPE trim_type = ON_BrepTrim::mated;
01807 for ( int eti = 0; eti < edge_trim_count0; eti++ )
01808 {
01809 ON_BrepTrim& other_trim = m_T[edge.m_ti[eti]];
01810 if ( other_trim.m_li == loop.m_loop_index )
01811 {
01812 other_trim.m_type = ON_BrepTrim::seam;
01813 trim_type = ON_BrepTrim::seam;
01814 break;
01815 }
01816 }
01817 trim.m_type = trim_type;
01818 }
01819 return trim;
01820 }
01821
01822
01823 ON_BrepTrim&
01824 ON_Brep::NewTrim( ON_BOOL32 bRev3d, ON_BrepLoop& loop, int c2i )
01825 {
01826 m_is_solid = 0;
01827 ON_BrepTrim& trim = NewTrim( c2i );
01828 trim.m_bRev3d = bRev3d ? true : false;
01829 trim.m_li = loop.m_loop_index;
01830 loop.m_ti.Append(trim.m_trim_index);
01831 if ( c2i >= 0 && c2i < m_C2.Count() )
01832 {
01833 const ON_Curve* c2 = m_C2[c2i];
01834 if ( c2 )
01835 {
01836 ON_BoundingBox c2_bbox;
01837 if ( c2->GetBoundingBox(c2_bbox) )
01838 {
01839 c2_bbox.m_min.z = 0.0;
01840 c2_bbox.m_max.z = 0.0;
01841 if ( loop.m_ti.Count() == 1 )
01842 loop.m_pbox = c2_bbox;
01843 else
01844 loop.m_pbox.Union( c2_bbox );
01845 }
01846 }
01847 }
01848 return trim;
01849 }
01850
01851 ON_BrepTrim&
01852 ON_Brep::NewSingularTrim(const ON_BrepVertex& vertex,ON_BrepLoop& loop, ON_Surface::ISO iso, int c2i)
01853 {
01854 ON_BrepTrim& trim = NewTrim(false,loop,c2i);
01855 trim.m_vi[0] = vertex.m_vertex_index;
01856 trim.m_vi[1] = trim.m_vi[0];
01857 trim.m_type = ON_BrepTrim::singular;
01858 trim.m_iso = iso;
01859 trim.m_tolerance[0] = 0.0;
01860 trim.m_tolerance[1] = 0.0;
01861 trim.m__legacy_2d_tol = 0.0;
01862 trim.m__legacy_3d_tol = 0.0;
01863 trim.m__legacy_flags_Set(-1,1);
01864 return trim;
01865 }
01866
01867 void ON_Brep::Append( const ON_Brep& b )
01868 {
01869 int i, j, jcnt;
01870
01871 const int vcount0 = m_V.Count();
01872 const int ecount0 = m_E.Count();
01873 const int fcount0 = m_F.Count();
01874 const int tcount0 = m_T.Count();
01875 const int lcount0 = m_L.Count();
01876 const int c2count0 = m_C2.Count();
01877 const int c3count0 = m_C3.Count();
01878 const int scount0 = m_S.Count();
01879
01880 const int vcount1 = b.m_V.Count();
01881 const int ecount1 = b.m_E.Count();
01882 const int fcount1 = b.m_F.Count();
01883 const int tcount1 = b.m_T.Count();
01884 const int lcount1 = b.m_L.Count();
01885 const int c2count1 = b.m_C2.Count();
01886 const int c3count1 = b.m_C3.Count();
01887 const int scount1 = b.m_S.Count();
01888
01889
01890 ON_Object* obj;
01891 ON_Curve* c;
01892 ON_Surface* s;
01893 for ( i = 0; i < scount1; i++ ) {
01894 s = b.m_S[i];
01895 if ( s ) {
01896 obj = s->Duplicate();
01897 s = ON_Surface::Cast(obj);
01898 if ( !s )
01899 delete obj;
01900 }
01901 m_S.Append(s);
01902 }
01903 for ( i = 0; i < c2count1; i++ ) {
01904 c = b.m_C2[i];
01905 if ( c ) {
01906 obj = c->Duplicate();
01907 c = ON_Curve::Cast(obj);
01908 if ( !c )
01909 delete obj;
01910 }
01911 m_C2.Append(c);
01912 }
01913 for ( i = 0; i < c3count1; i++ ) {
01914 c = b.m_C3[i];
01915 if ( c ) {
01916 obj = c->Duplicate();
01917 c = ON_Curve::Cast(obj);
01918 if ( !c )
01919 delete obj;
01920 }
01921 m_C3.Append(c);
01922 }
01923
01924
01925 m_V.Append( b.m_V.Count(), b.m_V.Array() );
01926 m_E.Append( b.m_E.Count(), b.m_E.Array() );
01927 m_F.Append( b.m_F.Count(), b.m_F.Array() );
01928 m_T.Append( b.m_T.Count(), b.m_T.Array() );
01929 m_L.Append( b.m_L.Count(), b.m_L.Array() );
01930
01931
01932 for ( i = 0; i < vcount1; i++ ) {
01933 ON_BrepVertex& vertex = m_V[vcount0+i];
01934 if ( vertex.m_vertex_index >= 0 )
01935 vertex.m_vertex_index += vcount0;
01936 else
01937 vertex.m_vertex_index = -1;
01938 jcnt = vertex.m_ei.Count();
01939 for ( j = 0; j < jcnt; j++ ) {
01940 if ( vertex.m_ei[j] >=0 )
01941 vertex.m_ei[j] += ecount0;
01942 }
01943 }
01944
01945 for ( i = 0; i < ecount1; i++ )
01946 {
01947 ON_BrepEdge& edge = m_E[ecount0+i];
01948 if ( edge.m_edge_index >= 0 )
01949 edge.m_edge_index += ecount0;
01950 else
01951 edge.m_edge_index = -1;
01952 if ( edge.m_c3i >= 0 )
01953 edge.m_c3i += c3count0;
01954 if ( edge.m_vi[0] >= 0 )
01955 edge.m_vi[0] += vcount0;
01956 if ( edge.m_vi[1] >= 0 )
01957 edge.m_vi[1] += vcount0;
01958 jcnt = edge.m_ti.Count();
01959 for ( j = 0; j < jcnt; j++ ) {
01960 if ( edge.m_ti[j] >= 0 )
01961 edge.m_ti[j] += tcount0;
01962 }
01963 edge.m_brep = this;
01964 if (edge.m_c3i >= 0)
01965 edge.SetProxyCurve( m_C3[edge.m_c3i], b.m_E[i].ProxyCurveDomain() );
01966 else
01967 edge.SetProxyCurve( 0, b.m_E[i].ProxyCurveDomain() );
01968 if ( b.m_E[i].ProxyCurveIsReversed() != edge.ProxyCurveIsReversed() )
01969 edge.ON_CurveProxy::Reverse();
01970 edge.SetDomain( b.m_E[i].Domain() );
01971 }
01972
01973 for ( i = 0; i < tcount1; i++ ) {
01974 ON_BrepTrim& trim = m_T[tcount0+i];
01975 trim.m_brep = this;
01976 if ( trim.m_trim_index == i )
01977 trim.m_trim_index = tcount0+i;
01978 else
01979 trim.m_trim_index = -1;
01980 if ( trim.m_c2i >= 0 )
01981 trim.m_c2i += c2count0;
01982 if ( trim.m_ei >= 0 )
01983 trim.m_ei += ecount0;
01984 if ( trim.m_vi[0] >= 0 )
01985 trim.m_vi[0] += vcount0;
01986 if ( trim.m_vi[1] >= 0 )
01987 trim.m_vi[1] += vcount0;
01988 if ( trim.m_li >= 0 )
01989 trim.m_li += lcount0;
01990 if (trim.m_c2i >= 0)
01991 trim.SetProxyCurve( m_C2[trim.m_c2i], b.m_T[i].ProxyCurveDomain() );
01992 else
01993 trim.SetProxyCurve( 0, b.m_T[i].ProxyCurveDomain() );
01994 if ( b.m_T[i].ProxyCurveIsReversed() != trim.ProxyCurveIsReversed() )
01995 trim.ON_CurveProxy::Reverse();
01996 trim.SetDomain( b.m_T[i].Domain() );
01997 }
01998
01999 for ( i = 0; i < lcount1; i++ )
02000 {
02001 ON_BrepLoop& loop = m_L[lcount0+i];
02002 if ( loop.m_loop_index >= 0 )
02003 loop.m_loop_index += lcount0;
02004 else
02005 loop.m_loop_index = -1;
02006 jcnt = loop.m_ti.Count();
02007 for ( j = 0; j < jcnt; j++ ) {
02008 if ( loop.m_ti[j] >= 0)
02009 loop.m_ti[j] += tcount0;
02010 }
02011 if ( loop.m_fi >= 0 )
02012 loop.m_fi += fcount0;
02013 loop.m_brep = this;
02014 }
02015
02016 for ( i = 0; i < fcount1; i++ ) {
02017 ON_BrepFace& face = m_F[fcount0+i];
02018 if ( face.m_face_index >= 0 )
02019 face.m_face_index += fcount0;
02020 else
02021 face.m_face_index = -1;
02022 jcnt = face.m_li.Count();
02023 for ( j = 0; j < jcnt; j++ ) {
02024 if ( face.m_li[j] >= 0 )
02025 face.m_li[j] += lcount0;
02026 }
02027 if ( face.m_si >= 0 )
02028 {
02029 face.m_si += scount0;
02030 face.SetProxySurface(m_S[face.m_si]);
02031 }
02032 else
02033 {
02034 face.SetProxySurface( 0 );
02035 }
02036 face.m_brep = this;
02037 }
02038
02039
02040 if (m_bbox.IsValid() && b.BoundingBox().IsValid())
02041 m_bbox.Union(b.BoundingBox());
02042 else m_bbox.Destroy();
02043
02044 m_is_solid = 0;
02045
02046 DestroyMesh(ON::any_mesh);
02047
02048 return;
02049 }
02050
02051 ON_BrepLoop&
02052 ON_Brep::NewLoop( ON_BrepLoop::TYPE looptype )
02053 {
02054 m_is_solid = 0;
02055 int li = m_L.Count();
02056 m_L.Reserve(li+1);
02057 m_L.SetCount(li+1);
02058 ON_BrepLoop& loop = m_L.Array()[li];
02059 loop.m_loop_index = li;
02060 loop.m_type = looptype;
02061 loop.m_brep = this;
02062 return loop;
02063 }
02064
02065 ON_BrepLoop&
02066 ON_Brep::NewLoop( ON_BrepLoop::TYPE looptype, ON_BrepFace& face )
02067 {
02068 m_is_solid = 0;
02069 ON_BrepLoop& loop = NewLoop( looptype );
02070 loop.m_fi = face.m_face_index;
02071 if ( ON_BrepLoop::outer == looptype )
02072 {
02073
02074
02075 face.m_li.Insert(0,loop.m_loop_index);
02076 }
02077 else
02078 {
02079 face.m_li.Append(loop.m_loop_index);
02080 }
02081 loop.m_brep = this;
02082 return loop;
02083 }
02084
02085 ON_BrepLoop* ON_Brep::NewOuterLoop( int face_index )
02086 {
02087 m_is_solid = 0;
02088 int vid[4] = {-1,-1,-1,-1};
02089 int eid[4] = {-1,-1,-1,-1};
02090 ON_BOOL32 bRev3d[4] = {0,0,0,0};
02091 return NewOuterLoop( face_index,vid,eid,bRev3d);
02092 }
02093
02094 ON_BrepFace& ON_Brep::NewFace( int si )
02095 {
02096 m_bbox.Destroy();
02097 m_is_solid = 0;
02098 int fi = m_F.Count();
02099 m_F.Reserve(fi+1);
02100 m_F.SetCount(fi+1);
02101 ON_BrepFace& face = m_F.Array()[fi];
02102 face.m_face_index = fi;
02103 face.m_si = si;
02104 face.m_brep = this;
02105 if ( si >= 0 && si < m_S.Count() )
02106 {
02107 face.SetProxySurface(m_S[si]);
02108 if ( face.ProxySurface() )
02109 face.m_bbox = face.ProxySurface()->BoundingBox();
02110 }
02111 return face;
02112 }
02113
02114 ON_BrepFace* ON_Brep::NewFace( const ON_Surface& surface )
02115 {
02116 m_bbox.Destroy();
02117 m_is_solid = 0;
02118 ON_BrepFace* face = NULL;
02119 ON_Surface* pSurface = surface.DuplicateSurface();
02120 if ( pSurface )
02121 {
02122 int vid[4] = {-1,-1,-1,-1};
02123 int eid[4] = {-1,-1,-1,-1};
02124 ON_BOOL32 bRev3d[4] = {0,0,0,0};
02125 face = NewFace(pSurface,vid,eid,bRev3d);
02126 }
02127 return face;
02128 }
02129
02130
02131
02132 bool
02133 ON_Brep::SetTrimIsoFlags()
02134 {
02135 bool rc = true;
02136 int fi;
02137 const int fcnt = m_F.Count();
02138 for ( fi = 0; fi < fcnt; fi++ ) {
02139 if ( !SetTrimIsoFlags( m_F[fi] ) )
02140 rc = false;
02141 }
02142 return rc;
02143 }
02144
02145 bool
02146 ON_Brep::SetTrimIsoFlags( ON_BrepFace& face )
02147 {
02148 bool rc = true;
02149 int fli;
02150 const int face_loop_count = face.m_li.Count();
02151 for ( fli = 0; fli < face_loop_count; fli++ ) {
02152 if ( !SetTrimIsoFlags( m_L[face.m_li[fli]] ) )
02153 rc = false;
02154 }
02155 return rc;
02156 }
02157
02158 bool
02159 ON_Brep::SetTrimIsoFlags( ON_BrepLoop& loop )
02160 {
02161 bool rc = true;
02162 int lti;
02163 const int loop_trim_count = loop.m_ti.Count();
02164 for ( lti = 0; lti < loop_trim_count; lti++ ) {
02165 if ( !SetTrimIsoFlags( m_T[loop.m_ti[lti]] ) )
02166 rc = false;
02167 }
02168 return rc;
02169 }
02170
02171 bool
02172 ON_Brep::SetTrimIsoFlags( ON_BrepTrim& trim )
02173 {
02174 bool rc = false;
02175 if ( trim.m_li >= 0 && trim.m_li < m_L.Count() )
02176 {
02177 const int fi = m_L[trim.m_li].m_fi;
02178 if ( fi >= 0 && fi < m_F.Count() )
02179 {
02180 const ON_Surface* pS = m_F[fi].SurfaceOf();
02181 if ( pS )
02182 {
02183 const ON_Curve* pC = (trim.m_c2i >= 0 && trim.m_c2i < m_C2.Count())
02184 ? m_C2[trim.m_c2i]
02185 : 0;
02186 if ( pC )
02187 {
02188 ON_Interval PD = trim.ProxyCurveDomain();
02189 trim.m_iso = pS->IsIsoparametric( *pC, &PD);
02190 rc = true;
02191 }
02192 }
02193 }
02194 }
02195 return rc;
02196 }
02197
02198 bool
02199 ON_Brep::SetTrimTypeFlags( ON_BOOL32 bLazy )
02200 {
02201 bool rc = true;
02202 int fi;
02203 const int fcnt = m_F.Count();
02204 for ( fi = 0; fi < fcnt; fi++ ) {
02205 if ( !SetTrimTypeFlags( m_F[fi], bLazy ) )
02206 rc = false;
02207 }
02208 return rc;
02209 }
02210
02211 bool
02212 ON_Brep::SetTrimTypeFlags( ON_BrepFace& face, ON_BOOL32 bLazy )
02213 {
02214 bool rc = true;
02215 int fli;
02216 const int face_loop_count = face.m_li.Count();
02217 for ( fli = 0; fli < face_loop_count; fli++ ) {
02218 if ( !SetTrimTypeFlags( m_L[face.m_li[fli]], bLazy ) )
02219 rc = false;
02220 }
02221 return rc;
02222 }
02223
02224 bool
02225 ON_Brep::SetTrimTypeFlags( ON_BrepLoop& loop, ON_BOOL32 bLazy )
02226 {
02227 bool rc = true;
02228 int lti;
02229 const int loop_trim_count = loop.m_ti.Count();
02230 for ( lti = 0; lti < loop_trim_count; lti++ ) {
02231 if ( !SetTrimTypeFlags( m_T[loop.m_ti[lti]], bLazy ) )
02232 rc = false;
02233 }
02234 return rc;
02235 }
02236
02237 ON_BrepTrim::TYPE ON_Brep::TrimType( const ON_BrepTrim& trim, ON_BOOL32 bLazy ) const
02238 {
02239 ON_BrepTrim::TYPE trim_type = bLazy ? trim.m_type : ON_BrepTrim::unknown;
02240 int eti, other_ti;
02241
02242 if ( trim_type == ON_BrepTrim::unknown && trim.m_li >= 0 && trim.m_li < m_L.Count() )
02243 {
02244 const ON_BrepLoop& loop = m_L[trim.m_li];
02245 if ( loop.m_type == ON_BrepLoop::ptonsrf )
02246 trim_type = ON_BrepTrim::ptonsrf;
02247 else if (loop.m_type == ON_BrepLoop::crvonsrf )
02248 trim_type = ON_BrepTrim::crvonsrf;
02249 else if ( trim.m_ei == -1 )
02250 {
02251 trim_type = ON_BrepTrim::singular;
02252 }
02253 else if ( trim.m_ei >= 0 && trim.m_ei < m_E.Count() )
02254 {
02255 const ON_BrepEdge& edge = m_E[trim.m_ei];
02256 if ( edge.m_ti.Count() == 1 && edge.m_ti[0] == trim.m_trim_index )
02257 {
02258 trim_type = ON_BrepTrim::boundary;
02259 }
02260 else if ( edge.m_ti.Count() > 1 )
02261 {
02262 trim_type = ON_BrepTrim::mated;
02263
02264 for ( eti = 0; eti < edge.m_ti.Count(); eti++ )
02265 {
02266 other_ti = edge.m_ti[eti];
02267 if ( other_ti != trim.m_trim_index && other_ti >= 0 && other_ti < m_T.Count() )
02268 {
02269 if ( m_T[other_ti].m_li == trim.m_li )
02270 {
02271 trim_type = ON_BrepTrim::seam;
02272 break;
02273 }
02274 }
02275 }
02276 }
02277 }
02278 }
02279 return trim_type;
02280 }
02281
02282 bool
02283 ON_Brep::SetTrimTypeFlags( ON_BrepTrim& trim, ON_BOOL32 bLazy )
02284 {
02285 if ( !bLazy || trim.m_type == ON_BrepTrim::unknown)
02286 trim.m_type = TrimType(trim,false);
02287 return ((trim.m_type != ON_BrepTrim::unknown)?true:false);
02288 }
02289
02290 bool
02291 ON_Brep::GetTrim2dStart(int trim_index,
02292 ON_2dPoint& P
02293 ) const
02294
02295 {
02296 if (trim_index < 0 || trim_index >= m_T.Count())
02297 return false;
02298 const ON_BrepTrim& trim = m_T[trim_index];
02299 ON_3dPoint pp;
02300 if (!trim.EvPoint(trim.Domain()[0], pp))
02301 return false;
02302 P = pp;
02303 return true;
02304 }
02305
02306 bool
02307 ON_Brep::GetTrim2dEnd(int trim_index,
02308 ON_2dPoint& P
02309 ) const
02310
02311 {
02312 if (trim_index < 0 || trim_index >= m_T.Count())
02313 return false;
02314 const ON_BrepTrim& trim = m_T[trim_index];
02315 ON_3dPoint pp;
02316 if (!trim.EvPoint(trim.Domain()[1], pp))
02317 return false;
02318 P = pp;
02319 return true;
02320 }
02321
02322 bool
02323 ON_Brep::GetTrim3dStart(int trim_index,
02324 ON_3dPoint& P
02325 ) const
02326 {
02327 const ON_Surface* srf = 0;
02328 ON_3dPoint uv;
02329 if ( trim_index >= 0 && trim_index < m_T.Count() )
02330 {
02331 const ON_BrepTrim& trim = m_T[trim_index];
02332 if ( trim.m_li >= 0 && trim.m_li < m_L.Count() )
02333 {
02334 const int fi = m_L[trim.m_li].m_fi;
02335 if ( fi >= 0 && fi < m_F.Count() )
02336 {
02337 if ( trim.Evaluate(trim.Domain()[0],0,3,&uv.x) )
02338 {
02339 srf = m_F[fi].SurfaceOf();
02340 }
02341 }
02342 }
02343 }
02344 return (srf && srf->EvPoint(uv.x, uv.y, P) ? true : false);
02345 }
02346
02347 bool
02348 ON_Brep::GetTrim3dEnd(int trim_index,
02349 ON_3dPoint& P
02350 ) const
02351
02352 {
02353 const ON_Surface* srf = 0;
02354 ON_3dPoint uv;
02355 if ( trim_index >= 0 && trim_index < m_T.Count() )
02356 {
02357 const ON_BrepTrim& trim = m_T[trim_index];
02358 if ( trim.m_li >= 0 && trim.m_li < m_L.Count() )
02359 {
02360 const int fi = m_L[trim.m_li].m_fi;
02361 if ( fi >= 0 && fi < m_F.Count() )
02362 {
02363 if ( trim.Evaluate(trim.Domain()[1],0,3,&uv.x) )
02364 {
02365 srf = m_F[fi].SurfaceOf();
02366 }
02367 }
02368 }
02369 }
02370 return (srf && srf->EvPoint(uv.x, uv.y, P) ? true : false);
02371 }
02372
02373
02374 ON_BrepLoop::TYPE
02375 ON_Brep::ComputeLoopType( const ON_BrepLoop& loop ) const
02376 {
02377
02378
02379
02380
02381 ON_BrepLoop::TYPE loop_type = ON_BrepLoop::unknown;
02382
02383 int loop_dir = LoopDirection( loop );
02384 if ( 1 == loop_dir )
02385 loop_type = ON_BrepLoop::outer;
02386 else if ( -1 == loop_dir )
02387 loop_type = ON_BrepLoop::inner;
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434 return loop_type;
02435 }
02436
02437
02438 bool
02439 ON_Brep::IsValidTrim( int trim_index, ON_TextLog* text_log ) const
02440 {
02441 if ( trim_index < 0 || trim_index >= m_T.Count() )
02442 {
02443 if ( text_log )
02444 {
02445 text_log->Print("brep trim_index = %d (should be >=0 and <%d=brep.m_T.Count()).\n",
02446 trim_index, m_T.Count());
02447 }
02448 return ON_BrepIsNotValid();
02449 }
02450 const ON_BrepTrim& trim = m_T[trim_index];
02451 if ( trim.m_trim_index != trim_index )
02452 {
02453 if ( text_log )
02454 {
02455 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02456 text_log->PushIndent();
02457 text_log->Print("trim.m_trim_index = %d (should be %d).\n",
02458 trim.m_trim_index, trim_index );
02459 text_log->PopIndent();
02460 }
02461 return ON_BrepIsNotValid();
02462 }
02463 if ( !trim.IsValid(text_log) )
02464 {
02465 if ( text_log )
02466 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02467 return ON_BrepIsNotValid();
02468 }
02469 if ( trim.m_c2i < 0 || trim.m_c2i >= m_C2.Count() )
02470 {
02471 if ( text_log )
02472 {
02473 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02474 text_log->PushIndent();
02475 text_log->Print( "trim.m_c2i = %d (should be >=0 and <%d).\n", trim.m_c2i, 0, m_C2.Count() );
02476 text_log->PopIndent();
02477 }
02478 return ON_BrepIsNotValid();
02479 }
02480 const ON_Curve* pC = m_C2[trim.m_c2i];
02481 if ( !pC )
02482 {
02483 if ( text_log )
02484 {
02485 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02486 text_log->PushIndent();
02487 text_log->Print("trim.m_c2i = %d and ON_Brep.m_C2[%d] is NULL\n", trim.m_c2i, trim.m_c2i );
02488 text_log->PopIndent();
02489 }
02490 return ON_BrepIsNotValid();
02491 }
02492 int c2_dim = pC->Dimension();
02493 if ( c2_dim != 2 )
02494 {
02495 if ( text_log )
02496 {
02497 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02498 text_log->PushIndent();
02499 text_log->Print("trim.m_c2i = %d and ON_Brep.m_C2[%d]->Dimension() = %d (should be 2).\n", trim.m_c2i, trim.m_c2i, c2_dim );
02500 text_log->PopIndent();
02501 }
02502 return ON_BrepIsNotValid();
02503 }
02504
02505 if ( pC != trim.ProxyCurve() )
02506 {
02507 if ( text_log )
02508 {
02509 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02510 text_log->PushIndent();
02511 text_log->Print("trim.ProxyCurve() != m_C2[trim.m_c2i].\n");
02512 text_log->PopIndent();
02513 }
02514 return ON_BrepIsNotValid();
02515 }
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529 ON_Interval trim_domain = trim.Domain();
02530 ON_Interval c2_domain = pC->Domain();
02531 if ( !trim_domain.IsIncreasing() )
02532 {
02533 if ( text_log )
02534 {
02535 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02536 text_log->PushIndent();
02537 text_log->Print("trim.Domain() = (%g,%g) (should be an increasing interval).\n", trim_domain[0], trim_domain[1] );
02538 text_log->PopIndent();
02539 }
02540 return ON_BrepIsNotValid();
02541 }
02542 if ( !c2_domain.Includes(trim_domain) )
02543 {
02544 if ( text_log )
02545 {
02546 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02547 text_log->PushIndent();
02548 text_log->Print("trim.Domain() = (%g,%g) is not included in brep.m_C2[trim.m_c2i=%d]->Domain() = (%g,%g)\n",
02549 trim_domain[0], trim_domain[1], trim.m_c2i, c2_domain[0], c2_domain[1] );
02550 text_log->PopIndent();
02551 }
02552 return ON_BrepIsNotValid();
02553 }
02554 int vi0 = trim.m_vi[0];
02555 int vi1 = trim.m_vi[1];
02556 if ( vi0 < 0 || vi0 >= m_V.Count() )
02557 {
02558 if ( text_log )
02559 {
02560 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02561 text_log->PushIndent();
02562 text_log->Print("trim.m_vi[0] = %d (should be >= 0 and < %d=brep.m_V.Count()).\n",
02563 trim_index, vi0, m_V.Count() );
02564 text_log->PopIndent();
02565 }
02566 return ON_BrepIsNotValid();
02567 }
02568 if ( vi1 < 0 || vi1 >= m_V.Count() )
02569 {
02570 if ( text_log )
02571 {
02572 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02573 text_log->PushIndent();
02574 text_log->Print("trim.m_vi[1] = %d (should be >= 0 and < %d=brep.m_V.Count()).\n",
02575 trim_index, vi1, m_V.Count() );
02576 text_log->PopIndent();
02577 }
02578 return ON_BrepIsNotValid();
02579 }
02580 const int ei = trim.m_ei;
02581 int trim_eti = -1;
02582 if ( trim.m_type == ON_BrepTrim::singular )
02583 {
02584
02585 if ( ei != -1 )
02586 {
02587 if ( text_log )
02588 {
02589 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02590 text_log->PushIndent();
02591 text_log->Print("trim.m_type = singular but trim.m_ei = %d (should be -1)\n",ei);
02592 text_log->PopIndent();
02593 }
02594 return ON_BrepIsNotValid();
02595 }
02596 if ( vi0 != vi1 )
02597 {
02598 if ( text_log )
02599 {
02600 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02601 text_log->PushIndent();
02602 text_log->Print("trim.m_type = singular but trim.m_vi[] = [%d,%d] (the m_vi[] values should be equal).\n",
02603 vi0,vi1);
02604 text_log->PopIndent();
02605 }
02606 return ON_BrepIsNotValid();
02607 }
02608 if ( pC->IsClosed() )
02609 {
02610 if ( text_log )
02611 {
02612 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02613 text_log->PushIndent();
02614 text_log->Print("trim.m_type = singular but brep.m_C2[trim.m_c2i=%d]->IsClosed() is true.\n",
02615 trim.m_c2i,trim.m_c2i);
02616 text_log->PopIndent();
02617 }
02618 return ON_BrepIsNotValid();
02619 }
02620 }
02621 else if ( trim.m_type != ON_BrepTrim::ptonsrf )
02622 {
02623
02624 if ( ei < 0 || ei >= m_E.Count() )
02625 {
02626 if ( text_log )
02627 {
02628 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02629 text_log->PushIndent();
02630 text_log->Print("trim.m_type != singular and trim.m_ei = %d (m_ei should be >=0 and <brep.m_E.Count()=%d\n",
02631 trim.m_ei,m_E.Count());
02632 text_log->PopIndent();
02633 }
02634 return ON_BrepIsNotValid();
02635 }
02636 const ON_BrepEdge& edge = m_E[ei];
02637 if ( edge.m_vi[trim.m_bRev3d?1:0] != vi0 )
02638 {
02639 if ( text_log )
02640 {
02641 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02642 text_log->PushIndent();
02643 text_log->Print("trim.m_vi[0] != brep.m_E[trim.m_ei=%d].m_vi[trim.m_bRev3d?1:0]\n",ei);
02644 text_log->PopIndent();
02645 }
02646 return ON_BrepIsNotValid();
02647 }
02648 if ( edge.m_vi[trim.m_bRev3d?0:1] != vi1 )
02649 {
02650 if ( text_log )
02651 {
02652 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02653 text_log->PushIndent();
02654 text_log->Print("trim.m_vi[1] != brep.m_E[trim.m_ei=%d].m_vi[trim.m_bRev3d?0:1]\n",ei);
02655 text_log->PopIndent();
02656 }
02657 return ON_BrepIsNotValid();
02658 }
02659 if ( trim_domain == c2_domain && pC->IsClosed() )
02660 {
02661
02662 if ( vi0 != vi1 )
02663 {
02664 if ( text_log )
02665 {
02666 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02667 text_log->PushIndent();
02668 text_log->Print("trim.m_vi[] = [%d,%d] but brep.m_C2[trim.m_c2i=%d]->IsClosed()=true\n",
02669 vi0, vi1, trim.m_c2i );
02670 text_log->PopIndent();
02671 }
02672 return ON_BrepIsNotValid();
02673 }
02674 }
02675 else if ( vi0 == vi1 )
02676 {
02677
02678 }
02679 else
02680 {
02681
02682
02683 }
02684 int i;
02685 for ( i = 0; i < edge.m_ti.Count(); i++ )
02686 {
02687 if ( edge.m_ti[i] == trim_index )
02688 {
02689 trim_eti = i;
02690 break;
02691 }
02692 }
02693
02694 if ( trim_eti < 0 )
02695 {
02696 if ( text_log )
02697 {
02698 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02699 text_log->PushIndent();
02700 text_log->Print("trim index %d is not in brep.m_E[trim.m_ei=%d].m_ti[]\n",
02701 trim_index, trim.m_ei );
02702 text_log->PopIndent();
02703 }
02704 return ON_BrepIsNotValid();
02705 }
02706
02707 if ( edge.m_ti.Count() == 2 )
02708 {
02709 int other_ti = edge.m_ti[ (edge.m_ti[0]==trim_index)?1:0 ];
02710 if ( other_ti >= 0 && other_ti < m_T.Count() && other_ti != trim_index )
02711 {
02712 const ON_BrepTrim& other_trim = m_T[other_ti];
02713 if ( other_trim.m_li == trim.m_li )
02714 {
02715 if ( trim.m_type != ON_BrepTrim::seam )
02716 {
02717 if ( text_log )
02718 {
02719 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02720 text_log->PushIndent();
02721 text_log->Print("trim.m_type!=seam but brep.m_E[trim.m_ei=%d] references two trims in loop trim.m_li=%d.\n",
02722 trim.m_ei,trim.m_li);
02723 text_log->PopIndent();
02724 }
02725 return ON_BrepIsNotValid();
02726 }
02727 }
02728 }
02729 }
02730 }
02731 if ( trim.m_li < 0 || trim.m_li >= m_L.Count() )
02732 {
02733 if ( text_log )
02734 {
02735 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02736 text_log->PushIndent();
02737 text_log->Print("trim.m_li = %d (should be >= 0 and <brep.m_L.Count()=%d\n", trim.m_li,m_L.Count() );
02738 text_log->PopIndent();
02739 }
02740 return ON_BrepIsNotValid();
02741 }
02742
02743 if ( trim.m_ei >= 0 && trim_eti < 0 )
02744 {
02745 if ( text_log )
02746 {
02747 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02748 text_log->PushIndent();
02749 text_log->Print("brep.m_E[trim.m_ei=%d].m_ti[] does not reference the trim.\n",trim.m_ei);
02750 text_log->PopIndent();
02751 }
02752 return ON_BrepIsNotValid();
02753 }
02754
02755
02756 switch ( trim.m_type )
02757 {
02758 case ON_BrepTrim::unknown:
02759 {
02760 if ( text_log )
02761 {
02762 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02763 text_log->PushIndent();
02764 text_log->Print("trim.m_type = unknown (should be set to the correct ON_BrepTrim::TYPE value)\n");
02765 text_log->PopIndent();
02766 }
02767 return ON_BrepIsNotValid();
02768 }
02769 break;
02770 case ON_BrepTrim::boundary:
02771 {
02772 const ON_BrepLoop& loop = m_L[trim.m_li];
02773 const ON_BrepEdge& edge = m_E[trim.m_ei];
02774 if ( edge.m_ti.Count() > 1 )
02775 {
02776 if ( text_log )
02777 {
02778 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02779 text_log->PushIndent();
02780 text_log->Print("trim.m_type = boundary but brep.m_E[trim.m_ei=%d] has 2 or more trims.\n",trim.m_ei);
02781 text_log->PopIndent();
02782 }
02783 return ON_BrepIsNotValid();
02784 }
02785 if ( loop.m_type != ON_BrepLoop::outer && loop.m_type != ON_BrepLoop::inner )
02786 {
02787 if ( text_log )
02788 {
02789 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02790 text_log->PushIndent();
02791 text_log->Print("trim.m_type = boundary but brep.m_L[trim.m_li=%d].m_type is not inner or outer.\n",trim.m_li);
02792 text_log->PopIndent();
02793 }
02794 return ON_BrepIsNotValid();
02795 }
02796 }
02797 break;
02798 case ON_BrepTrim::mated:
02799 {
02800 const ON_BrepLoop& loop = m_L[trim.m_li];
02801 const ON_BrepEdge& edge = m_E[trim.m_ei];
02802 if ( edge.m_ti.Count() < 2 )
02803 {
02804 if ( text_log )
02805 {
02806 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02807 text_log->PushIndent();
02808 text_log->Print("trim.m_type = mated but brep.m_E[trim.m_ei=%d] only references this trim.\n",trim.m_ei);
02809 text_log->PopIndent();
02810 }
02811 return ON_BrepIsNotValid();
02812 }
02813 if ( loop.m_type != ON_BrepLoop::outer && loop.m_type != ON_BrepLoop::inner )
02814 {
02815 if ( text_log )
02816 {
02817 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02818 text_log->PushIndent();
02819 text_log->Print("trim.m_type = mated but brep.m_L[trim.m_li=%d].m_type is not inner or outer.\n",trim.m_li);
02820 text_log->PopIndent();
02821 }
02822 return ON_BrepIsNotValid();
02823 }
02824 }
02825 break;
02826 case ON_BrepTrim::seam:
02827 {
02828 const ON_BrepLoop& loop = m_L[trim.m_li];
02829 const ON_BrepEdge& edge = m_E[trim.m_ei];
02830 if ( edge.m_ti.Count() < 2 )
02831 {
02832 if ( text_log )
02833 {
02834 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02835 text_log->PushIndent();
02836 text_log->Print("trim.m_type = seam but brep.m_E[trim.m_ei=%d] < 2.\n",trim.m_ei);
02837 text_log->PopIndent();
02838 }
02839 return ON_BrepIsNotValid();
02840 }
02841 int other_ti = -1;
02842 for ( int eti = 0; eti < edge.m_ti.Count(); eti++ )
02843 {
02844 if ( trim_eti == eti )
02845 continue;
02846 int i = edge.m_ti[eti];
02847 if ( i == trim_index )
02848 {
02849 if ( text_log )
02850 {
02851 text_log->Print("brep.m_E[%d] trim is not valid.\n",trim.m_ei);
02852 text_log->PushIndent();
02853 text_log->Print("edge.m_ti[%d] = m_ti[%d] = %d.\n",trim_eti,eti,trim_index);
02854 text_log->PopIndent();
02855 }
02856 return ON_BrepIsNotValid();
02857 }
02858
02859 if ( i < 0 || i >= m_T.Count() )
02860 {
02861 if ( text_log )
02862 {
02863 text_log->Print("brep.m_E[%d] trim is not valid.\n",trim.m_ei);
02864 text_log->PushIndent();
02865 text_log->Print("edge.m_ti[%d]=%d is not a valid m_T[] index.\n",eti,i);
02866 text_log->PopIndent();
02867 }
02868 return ON_BrepIsNotValid();
02869 }
02870
02871 const ON_BrepTrim& other_trim = m_T[i];
02872 if ( other_trim.m_type == ON_BrepTrim::seam && other_trim.m_li == trim.m_li )
02873 {
02874 if ( other_ti < 0 )
02875 other_ti = i;
02876 else
02877 {
02878 if ( text_log )
02879 {
02880 text_log->Print("brep.m_T[%d,%d, or %d] trim is not valid.\n",trim_index,other_ti,i);
02881 text_log->PushIndent();
02882 text_log->Print("All three trims have m_type = seam m_ei=%d and m_li = %d.\n",trim.m_ei,trim.m_li);
02883 text_log->PopIndent();
02884 }
02885 return ON_BrepIsNotValid();
02886 }
02887 }
02888 }
02889
02890 if ( other_ti < 0 )
02891 {
02892 if ( text_log )
02893 {
02894 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02895 text_log->PushIndent();
02896 text_log->Print("trim.m_type = seam but its other trim is not in the loop.\n");
02897 text_log->PopIndent();
02898 }
02899 return ON_BrepIsNotValid();
02900 }
02901
02902 if ( loop.m_type != ON_BrepLoop::outer && edge.m_ti.Count() <= 2 )
02903 {
02904 if ( text_log )
02905 {
02906 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02907 text_log->PushIndent();
02908 text_log->Print("trim.m_type = seam, the edge is manifold, but brep.m_L[trim.m_li=%d].m_type is not outer.\n",trim.m_li);
02909 text_log->PopIndent();
02910 }
02911 return ON_BrepIsNotValid();
02912 }
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930 }
02931 break;
02932 case ON_BrepTrim::singular:
02933
02934 if ( trim.m_iso != ON_Surface::W_iso && trim.m_iso != ON_Surface::N_iso &&
02935 trim.m_iso != ON_Surface::E_iso && trim.m_iso != ON_Surface::S_iso )
02936 {
02937 if ( text_log )
02938 {
02939 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02940 text_log->PushIndent();
02941 text_log->Print("trim.m_type = singular but trim.m_iso != N/S/E/W_iso\n");
02942 text_log->PopIndent();
02943 }
02944 return ON_BrepIsNotValid();
02945 }
02946 break;
02947 case ON_BrepTrim::crvonsrf:
02948 {
02949 const ON_BrepLoop& loop = m_L[trim.m_li];
02950 if ( loop.m_type != ON_BrepLoop::crvonsrf )
02951 {
02952 return ON_BrepIsNotValid();
02953 }
02954 if ( trim.m_c2i < 0 || trim.m_c2i >= m_C2.Count() )
02955 {
02956 return ON_BrepIsNotValid();
02957 }
02958 if ( trim.m_ei < 0 || trim.m_ei >= m_E.Count() )
02959 {
02960 return ON_BrepIsNotValid();
02961 }
02962 }
02963 break;
02964 case ON_BrepTrim::ptonsrf:
02965 {
02966 const ON_BrepLoop& loop = m_L[trim.m_li];
02967 if ( loop.m_type != ON_BrepLoop::ptonsrf )
02968 {
02969 return ON_BrepIsNotValid();
02970 }
02971 if ( trim.m_ei != -1 )
02972 {
02973 return ON_BrepIsNotValid();
02974 }
02975 if ( trim.m_c2i != -1 )
02976 {
02977 return ON_BrepIsNotValid();
02978 }
02979 if ( trim.m_pbox.m_min.x != trim.m_pbox.m_max.x || trim.m_pbox.m_min.y != trim.m_pbox.m_max.y || trim.m_pbox.m_min.z != trim.m_pbox.m_max.z )
02980 {
02981
02982 return ON_BrepIsNotValid();
02983 }
02984 if ( trim.m_pbox.m_min.x == ON_UNSET_VALUE || trim.m_pbox.m_min.y == ON_UNSET_VALUE || trim.m_pbox.m_min.z != 0.0 )
02985 {
02986
02987 return ON_BrepIsNotValid();
02988 }
02989 }
02990 break;
02991
02992 case ON_BrepTrim::slit:
02993 {
02994 if ( text_log )
02995 {
02996 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
02997 text_log->PushIndent();
02998 text_log->Print("trim.m_type = ON_BrepTrim::slit (should be set to the correct ON_BrepTrim::TYPE value)\n");
02999 text_log->PopIndent();
03000 }
03001 return ON_BrepIsNotValid();
03002 }
03003 break;
03004
03005 case ON_BrepTrim::trim_type_count:
03006 {
03007 if ( text_log )
03008 {
03009 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
03010 text_log->PushIndent();
03011 text_log->Print("trim.m_type = type_count (should be set to the correct ON_BrepTrim::TYPE value)\n");
03012 text_log->PopIndent();
03013 }
03014 return ON_BrepIsNotValid();
03015 }
03016 break;
03017
03018 default:
03019 {
03020 if ( text_log )
03021 {
03022 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
03023 text_log->PushIndent();
03024 text_log->Print("trim.m_type = garbage (should be set to the correct ON_BrepTrim::TYPE value)\n");
03025 text_log->PopIndent();
03026 }
03027 return ON_BrepIsNotValid();
03028 }
03029 break;
03030 }
03031
03032 if ( trim.m_tolerance[0] < 0.0 )
03033 {
03034 if ( text_log )
03035 {
03036 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
03037 text_log->PushIndent();
03038 text_log->Print("trim.m_tolerance[0] = %g (should be >= 0.0)\n",trim.m_tolerance[0]);
03039 text_log->PopIndent();
03040 }
03041 return ON_BrepIsNotValid();
03042 }
03043 if ( trim.m_tolerance[1] < 0.0 )
03044 {
03045 if ( text_log )
03046 {
03047 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
03048 text_log->PushIndent();
03049 text_log->Print("trim.m_tolerance[1] = %g (should be >= 0.0)\n",trim.m_tolerance[1]);
03050 text_log->PopIndent();
03051 }
03052 return ON_BrepIsNotValid();
03053 }
03054
03055 if ( !trim.m_pbox.IsValid() )
03056 {
03057 if ( text_log )
03058 {
03059 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
03060 text_log->PushIndent();
03061 text_log->Print("trim.m_pbox is not valid.\n");
03062 text_log->PopIndent();
03063 }
03064 return ON_BrepIsNotValid();
03065 }
03066
03067 if ( trim.m_brep != this )
03068 {
03069 if ( text_log )
03070 {
03071 text_log->Print("brep.m_T[%d] trim is not valid.\n",trim_index);
03072 text_log->PushIndent();
03073 text_log->Print("trim.m_brep does not point to parent brep.\n");
03074 text_log->PopIndent();
03075 }
03076 return ON_BrepIsNotValid();
03077 }
03078
03079 return true;
03080 }
03081
03082 bool
03083 ON_Brep::IsValidLoop( int loop_index, ON_TextLog* text_log ) const
03084 {
03085 if ( loop_index < 0 || loop_index >= m_L.Count() )
03086 {
03087 if ( text_log )
03088 {
03089 text_log->Print("brep loop_index = %d (should be >=0 and <%d=brep.m_L.Count()).\n",
03090 loop_index, m_L.Count());
03091 }
03092 return ON_BrepIsNotValid();
03093 }
03094 const ON_BrepLoop& loop = m_L[loop_index];
03095 if ( loop.m_loop_index != loop_index )
03096 {
03097 if ( text_log )
03098 {
03099 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03100 text_log->PushIndent();
03101 text_log->Print("loop.m_loop_index = %d (should be %d).\n",
03102 loop.m_loop_index, loop_index );
03103 text_log->PopIndent();
03104 }
03105 return ON_BrepIsNotValid();
03106 }
03107 if ( loop.m_fi < 0 || loop.m_fi >= m_F.Count() )
03108 {
03109 if ( text_log )
03110 {
03111 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03112 text_log->PushIndent();
03113 text_log->Print("loop.m_fi = %d (should be >= 0 and <brep.m_F.Count()=%d\n", loop.m_fi, m_F.Count() );
03114 text_log->PopIndent();
03115 }
03116 return ON_BrepIsNotValid();
03117 }
03118 const int loop_trim_count = loop.m_ti.Count();
03119 if ( loop_trim_count <= 0 )
03120 {
03121 if ( text_log )
03122 {
03123 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03124 text_log->PushIndent();
03125 text_log->Print("loop.m_ti.Count() is <= 0 (should be > 0)\n");
03126 text_log->PopIndent();
03127 }
03128 return ON_BrepIsNotValid();
03129 }
03130
03131 if ( loop.m_type != ON_BrepLoop::outer
03132 && loop.m_type != ON_BrepLoop::inner
03133 && loop.m_type != ON_BrepLoop::slit
03134 )
03135 {
03136 if ( text_log )
03137 {
03138 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03139 text_log->PushIndent();
03140 text_log->Print("loop.m_type = %d (must be %d=outer, %d=inner, or %d=slit)\n",
03141 loop.m_type,ON_BrepLoop::outer,ON_BrepLoop::inner,ON_BrepLoop::slit);
03142 text_log->PopIndent();
03143 }
03144 return ON_BrepIsNotValid();
03145 }
03146
03147
03148 if ( loop.m_brep != this )
03149 {
03150 if ( text_log )
03151 {
03152 text_log->Print("loop.m_L[%d] loop is not valid.\n",loop_index);
03153 text_log->PushIndent();
03154 text_log->Print("loop.m_brep does not point to parent brep.\n");
03155 text_log->PopIndent();
03156 }
03157 return ON_BrepIsNotValid();
03158 }
03159
03160
03161 int i, lti, ti;
03162 for ( lti = 0; lti < loop_trim_count; lti++ ) {
03163 ti = loop.m_ti[lti];
03164 for ( i = 0; i < lti; i++ ) {
03165 if ( loop.m_ti[i] == ti )
03166 {
03167 if ( text_log )
03168 {
03169 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03170 text_log->PushIndent();
03171 text_log->Print("loop.m_ti[%d] = loop.m_ti[%d] = %d (trim index can only appear once)\n",
03172 lti, i, ti);
03173 text_log->PopIndent();
03174 }
03175 return ON_BrepIsNotValid();
03176 }
03177 }
03178 if ( !IsValidTrim( ti, text_log ) )
03179 {
03180 if ( text_log )
03181 {
03182 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03183 text_log->PushIndent();
03184 text_log->Print("brep.m_T[loop.m_ti[%d]=%d] is not valid.\n",
03185 lti, ti);
03186 text_log->PopIndent();
03187 }
03188 return ON_BrepIsNotValid();
03189 }
03190 if ( m_T[ti].m_li != loop_index )
03191 {
03192 if ( text_log )
03193 {
03194 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03195 text_log->PushIndent();
03196 text_log->Print("brep.m_T[loop.m_ti[%d]=%d].m_li=%d (m_li should be %d).\n",
03197 lti, ti, m_T[ti].m_li, loop_index );
03198 text_log->PopIndent();
03199 }
03200 return ON_BrepIsNotValid();
03201 }
03202 }
03203
03204
03205 if ( ON_BrepLoop::slit == loop.m_type )
03206 {
03207 if ( loop.m_ti.Count() < 2 || 0 != (loop.m_ti.Count() % 2) )
03208 {
03209 if ( text_log )
03210 {
03211 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03212 text_log->PushIndent();
03213 text_log->Print("loop.m_type = slit but loop has %d trims\n",loop.m_ti.Count());
03214 text_log->PopIndent();
03215 }
03216 return ON_BrepIsNotValid();
03217 }
03218
03219 for ( int lti = 0; lti < loop.m_ti.Count(); lti++ )
03220 {
03221 int ti = loop.m_ti[lti];
03222 const ON_BrepTrim& trim = m_T[ti];
03223 if ( trim.m_type != ON_BrepTrim::seam )
03224 {
03225 if ( text_log )
03226 {
03227 text_log->Print("brep.m_L[%d] slit loop is not valid.\n",loop_index);
03228 text_log->PushIndent();
03229 text_log->Print("brep.m_T[loop.m_ti[%d]=%d].m_type = %d (should be %d = seam)\n",
03230 lti,ti,trim.m_type,ON_BrepTrim::seam);
03231 text_log->PopIndent();
03232 }
03233 return ON_BrepIsNotValid();
03234 }
03235 switch( trim.m_iso )
03236 {
03237 case ON_Surface::W_iso:
03238 case ON_Surface::E_iso:
03239 case ON_Surface::S_iso:
03240 case ON_Surface::N_iso:
03241 {
03242 if ( text_log )
03243 {
03244 text_log->Print("brep.m_L[%d] slit loop is not valid.\n",loop_index);
03245 text_log->PushIndent();
03246 text_log->Print("brep.m_T[loop.m_ti[%d]=%d].m_iso = E/W/N/S_iso (should be interior)\n",
03247 lti,ti);
03248 text_log->PopIndent();
03249 }
03250 return ON_BrepIsNotValid();
03251 }
03252 break;
03253
03254 case ON_Surface::not_iso:
03255 case ON_Surface::x_iso:
03256 case ON_Surface::y_iso:
03257 case ON_Surface::iso_count:
03258 break;
03259 }
03260 }
03261 }
03262
03263
03264
03265 int ci0, ci1, next_lti;
03266 ON_3dPoint P0, P1;
03267 const ON_Curve *pC0, *pC1;
03268 for ( lti = 0; lti < loop_trim_count; lti++ )
03269 {
03270
03271
03272 const ON_BrepTrim& trim0 = m_T[loop.m_ti[lti]];
03273 next_lti = (lti+1)%loop_trim_count;
03274 const ON_BrepTrim& trim1 = m_T[loop.m_ti[next_lti]];
03275 ON_Interval trim0_domain = trim0.Domain();
03276 ON_Interval trim1_domain = trim1.Domain();
03277 ci0 = trim0.m_c2i;
03278 ci1 = trim1.m_c2i;
03279 pC0 = m_C2[ci0];
03280 pC1 = m_C2[ci1];
03281 P0 = pC0->PointAt( trim0_domain[1] );
03282 P1 = pC1->PointAt( trim1_domain[0] );
03283 if ( !(P0-P1).IsTiny() )
03284 {
03285
03286
03287
03288
03289 double xtol = (fabs(P0.x) + fabs(P1.x))*1.0e-10;
03290 double ytol = (fabs(P0.y) + fabs(P1.y))*1.0e-10;
03291 if ( xtol < ON_ZERO_TOLERANCE )
03292 xtol = ON_ZERO_TOLERANCE;
03293 if ( ytol < ON_ZERO_TOLERANCE )
03294 ytol = ON_ZERO_TOLERANCE;
03295 double dx = fabs(P0.x-P1.x);
03296 double dy = fabs(P0.y-P1.y);
03297 if ( dx > xtol || dy > ytol )
03298 {
03299 if ( text_log )
03300 {
03301 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03302 text_log->PushIndent();
03303 text_log->Print("end of brep.m_T[loop.m_ti[%d]=%d]=(%g,%g) and start \n", lti, loop.m_ti[lti],P0.x,P0.y);
03304 text_log->Print("of brep.m_T[loop.m_ti[%d]=%d]=(%g,%g) do not match.\n",next_lti, loop.m_ti[next_lti],P1.x,P1.y);
03305 text_log->PopIndent();
03306 }
03307 return ON_BrepIsNotValid();
03308 }
03309 }
03310 }
03311
03312 if ( !loop.m_pbox.IsValid() )
03313 {
03314 if ( text_log )
03315 {
03316 text_log->Print("brep.m_L[%d] loop is not valid.\n",loop_index);
03317 text_log->PushIndent();
03318 text_log->Print("loop.m_pbox is not valid\n");
03319 text_log->PopIndent();
03320 }
03321 return ON_BrepIsNotValid();
03322 }
03323
03324 return true;
03325 }
03326
03327
03328 bool
03329 ON_Brep::IsValidFace( int face_index, ON_TextLog* text_log ) const
03330 {
03331 if ( face_index < 0 || face_index >= m_F.Count() )
03332 {
03333 if ( text_log )
03334 {
03335 text_log->Print("brep face_index = %d (should be >=0 and <%d=brep.m_F.Count()).\n",
03336 face_index, m_F.Count());
03337 }
03338 return ON_BrepIsNotValid();
03339 }
03340 const ON_BrepFace& face = m_F[face_index];
03341 if ( face.m_face_index != face_index )
03342 {
03343 if ( text_log )
03344 {
03345 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03346 text_log->PushIndent();
03347 text_log->Print("face.m_face_index = %d (should be %d).\n",
03348 face.m_face_index, face_index );
03349 text_log->PopIndent();
03350 }
03351 return ON_BrepIsNotValid();
03352 }
03353 if ( face.m_brep != this )
03354 {
03355 if ( text_log )
03356 {
03357 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03358 text_log->PushIndent();
03359 text_log->Print("face.m_brep does not point to parent brep.\n");
03360 text_log->PopIndent();
03361 }
03362 return ON_BrepIsNotValid();
03363 }
03364
03365 const int face_loop_count = face.m_li.Count();
03366 if ( face_loop_count <= 0 )
03367 {
03368 if ( text_log )
03369 {
03370 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03371 text_log->PushIndent();
03372 text_log->Print("face.m_li.Count() <= 0 (should be >= 1)\n");
03373 text_log->PopIndent();
03374 }
03375 return ON_BrepIsNotValid();
03376 }
03377
03378 int i, fli, li;
03379 for ( fli = 0; fli < face_loop_count; fli++ )
03380 {
03381 li = face.m_li[fli];
03382 for ( i = 0; i < fli; i++ )
03383 {
03384 if ( face.m_li[i] == li )
03385 {
03386 if ( text_log )
03387 {
03388 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03389 text_log->PushIndent();
03390 text_log->Print("face.m_li[%d]=face.m_li[%d]=%d (a loop index should appear once in face.m_li[])\n",
03391 fli,i,li);
03392 text_log->PopIndent();
03393 }
03394 return ON_BrepIsNotValid();
03395 }
03396 }
03397 if ( !IsValidLoop( li, text_log ) )
03398 {
03399 if ( text_log )
03400 {
03401 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03402 text_log->PushIndent();
03403 text_log->Print("brep.m_L[face.m_li[%d]=%d] is not valid.\n",fli,li);
03404 text_log->PopIndent();
03405 }
03406 return ON_BrepIsNotValid();
03407 }
03408 const ON_BrepLoop& loop = m_L[li];
03409 if ( loop.m_loop_index != li )
03410 {
03411 if ( text_log )
03412 {
03413 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03414 text_log->PushIndent();
03415 text_log->Print("face.m_li[%d]=%d is a deleted loop\n",
03416 fli,li);
03417 text_log->PopIndent();
03418 }
03419 return ON_BrepIsNotValid();
03420 }
03421 if ( loop.m_fi != face_index )
03422 {
03423 if ( text_log )
03424 {
03425 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03426 text_log->PushIndent();
03427 text_log->Print("face.m_li[%d]=%d but brep.m_L[%d].m_fi=%d (m_fi should be %d)\n",
03428 fli,li,li,loop.m_fi,face_index);
03429 text_log->PopIndent();
03430 }
03431 return ON_BrepIsNotValid();
03432 }
03433 if ( fli == 0 )
03434 {
03435 if ( loop.m_type != ON_BrepLoop::outer )
03436 {
03437 if ( text_log )
03438 {
03439 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03440 text_log->PushIndent();
03441 text_log->Print("brep.m_L[face.m_li[0]=%d].m_type is not outer.\n",li);
03442 text_log->PopIndent();
03443 }
03444 return ON_BrepIsNotValid();
03445 }
03446 }
03447 else
03448 {
03449 if ( loop.m_type != ON_BrepLoop::slit
03450 && loop.m_type != ON_BrepLoop::inner
03451 )
03452 {
03453 if ( text_log )
03454 {
03455 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03456 text_log->PushIndent();
03457 text_log->Print("brep.m_L[face.m_li[%d]=%d].m_type is not inner or slit.\n",fli,li);
03458 text_log->PopIndent();
03459 }
03460 return ON_BrepIsNotValid();
03461 }
03462 }
03463 }
03464
03465 const int si = face.m_si;
03466 if ( si < 0 || si >= m_S.Count() )
03467 {
03468 if ( text_log )
03469 {
03470 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03471 text_log->PushIndent();
03472 text_log->Print("face.m_si=%d (should be >=0 and <%d=m_S.Count())\n",
03473 face.m_si,m_S.Count());
03474 text_log->PopIndent();
03475 }
03476 return ON_BrepIsNotValid();
03477 }
03478
03479 if ( !m_S[si] )
03480 {
03481 if ( text_log )
03482 {
03483 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03484 text_log->PushIndent();
03485 text_log->Print("brep.m_S[face.m_si=%d] is NULL\n",face.m_si);
03486 text_log->PopIndent();
03487 }
03488 return ON_BrepIsNotValid();
03489 }
03490
03491 if ( m_S[si] != face.ProxySurface() )
03492 {
03493 if ( text_log )
03494 {
03495 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03496 text_log->PushIndent();
03497 text_log->Print("brep.m_S[face.m_si=%d] != face.ProxySurface().\n",si);
03498 text_log->PopIndent();
03499 }
03500 return ON_BrepIsNotValid();
03501 }
03502
03503 if ( face.ProxySurfaceIsTransposed() )
03504 {
03505 if ( text_log )
03506 {
03507 text_log->Print("brep.m_F[%d] face is not valid.\n",face_index);
03508 text_log->PushIndent();
03509 text_log->Print("face.ProxySurfaceIsTransposed() is true.\n");
03510 text_log->PopIndent();
03511 }
03512 return ON_BrepIsNotValid();
03513 }
03514
03515 return true;
03516 }
03517
03518 bool
03519 ON_Brep::IsValidEdge( int edge_index, ON_TextLog* text_log ) const
03520 {
03521 if ( edge_index < 0 || edge_index >= m_E.Count() )
03522 {
03523 if ( text_log )
03524 text_log->Print("brep edge_index = %d (should be >=0 and <%d=brep.m_E.Count() ).\n",
03525 edge_index, m_E.Count());
03526 return ON_BrepIsNotValid();
03527 }
03528 const ON_BrepEdge& edge = m_E[edge_index];
03529 if ( edge.m_brep != this )
03530 {
03531 if ( text_log )
03532 {
03533 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03534 text_log->PushIndent();
03535 text_log->Print("edge.m_brep does not point to parent brep\n");
03536 text_log->PopIndent();
03537 }
03538 return ON_BrepIsNotValid();
03539 }
03540 if ( edge.m_edge_index != edge_index )
03541 {
03542 if ( text_log )
03543 {
03544 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03545 text_log->PushIndent();
03546 text_log->Print("edge.m_edge_index = %d (should be %d).\n",
03547 edge.m_edge_index, edge_index );
03548 text_log->PopIndent();
03549 }
03550 return ON_BrepIsNotValid();
03551 }
03552 if ( !edge.IsValid(text_log) )
03553 {
03554 if ( text_log )
03555 {
03556 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03557 text_log->PushIndent();
03558 text_log->Print("edge is not a valid.\n");
03559 text_log->PopIndent();
03560 }
03561 return ON_BrepIsNotValid();
03562 }
03563
03564 const int ci = edge.m_c3i;
03565 if ( ci < 0 || ci >= m_C3.Count() )
03566 {
03567 if ( text_log )
03568 {
03569 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03570 text_log->PushIndent();
03571 text_log->Print("edge.m_c3i = %d (should be >=0 and <%d=m_C3.Count()\n",
03572 edge.m_c3i,m_C3.Count() );
03573 text_log->PopIndent();
03574 }
03575 return ON_BrepIsNotValid();
03576 }
03577
03578 if ( m_C3[ci] != edge.ProxyCurve() || 0 == m_C3[ci] )
03579 {
03580 if ( text_log )
03581 {
03582 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03583 text_log->PushIndent();
03584 text_log->Print("edge.m_curve != brep.m_C3[edge.m_c3i=%d]\n", edge.m_c3i );
03585 text_log->PopIndent();
03586 }
03587 return ON_BrepIsNotValid();
03588 }
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602 double t0, t1;
03603 if ( !edge.GetDomain( &t0, &t1 ) )
03604 {
03605 if ( text_log )
03606 {
03607 ON_Interval edom = edge.ProxyCurveDomain();
03608 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03609 text_log->PushIndent();
03610 text_log->Print( "edge.m_domain=(%g,%g) is not valid\n", edom[0], edom[1]);
03611 text_log->PopIndent();
03612 }
03613 return ON_BrepIsNotValid();
03614 }
03615 const int vi0 = edge.m_vi[0];
03616 const int vi1 = edge.m_vi[1];
03617 if ( vi0 < 0 || vi0 >= m_V.Count() )
03618 {
03619 if ( text_log )
03620 {
03621 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03622 text_log->PushIndent();
03623 text_log->Print("edge.m_vi[0]=%d (should be >=0 and <%d=m_V.Count()\n",
03624 vi0, m_V.Count() );
03625 text_log->PopIndent();
03626 }
03627 return ON_BrepIsNotValid();
03628 }
03629 if ( vi1 < 0 || vi1 >= m_V.Count() )
03630 {
03631 if ( text_log )
03632 {
03633 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03634 text_log->PushIndent();
03635 text_log->Print("edge.m_vi[1]=%d (should be >=0 and <%d=m_V.Count()\n",
03636 vi1, m_V.Count() );
03637 text_log->PopIndent();
03638 }
03639 return ON_BrepIsNotValid();
03640 }
03641 int evi;
03642 for ( evi = 0; evi < 2; evi++ )
03643 {
03644 const ON_BrepVertex& vertex = m_V[edge.m_vi[evi]];
03645
03646 if ( edge.m_vi[evi] != vertex.m_vertex_index )
03647 {
03648 if ( text_log )
03649 {
03650 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03651 text_log->PushIndent();
03652 text_log->Print("edge.m_vi[%d]=%d is a deleted vertex\n",
03653 evi,edge.m_vi[evi] );
03654 text_log->PopIndent();
03655 }
03656 return ON_BrepIsNotValid();
03657 }
03658
03659
03660 const int vertex_edge_count = vertex.m_ei.Count();
03661 ON_BOOL32 bFoundIt = false;
03662 int vei;
03663 for ( vei = 0; vei < vertex_edge_count && !bFoundIt; vei++ ) {
03664 bFoundIt = (vertex.m_ei[vei] == edge_index);
03665 }
03666 if ( !bFoundIt )
03667 {
03668 if ( text_log )
03669 {
03670 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03671 text_log->PushIndent();
03672 text_log->Print("edge.m_vi[%d]=%d but edge is not referenced in m_V[%d].m_ei[]\n",
03673 evi,edge.m_vi[evi],edge.m_vi[evi] );
03674 text_log->PopIndent();
03675 }
03676 return ON_BrepIsNotValid();
03677 }
03678 }
03679
03680 if ( edge.IsClosed() ) {
03681 if ( vi0 != vi1 )
03682 {
03683 if ( text_log )
03684 {
03685 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03686 text_log->PushIndent();
03687 text_log->Print("edge.m_vi[]=(%d,%d) but edge.IsClosed() is true\n",
03688 vi0,vi1);
03689 text_log->PopIndent();
03690 }
03691 return ON_BrepIsNotValid();
03692 }
03693 }
03694 else {
03695 if ( vi0 == vi1 )
03696 {
03697 if ( text_log )
03698 {
03699 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03700 text_log->PushIndent();
03701 text_log->Print("edge.m_vi[0]=edge.m_vi[1]=%d but edge.IsClosed() is false.\n",
03702 vi0);
03703 text_log->PopIndent();
03704 }
03705 return ON_BrepIsNotValid();
03706 }
03707 }
03708
03709 const int edge_trim_count = edge.m_ti.Count();
03710 if ( edge_trim_count < 0 )
03711 {
03712 if ( text_log )
03713 {
03714 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03715 text_log->PushIndent();
03716 text_log->Print("edge.m_ti.Count() < 0\n");
03717 text_log->PopIndent();
03718 }
03719 return ON_BrepIsNotValid();
03720 }
03721 int i, eti, ti;
03722 for (eti = 0; eti < edge_trim_count; eti++ )
03723 {
03724 ti = edge.m_ti[eti];
03725 if ( ti < 0 || ti >= m_T.Count() )
03726 {
03727 if ( text_log )
03728 {
03729 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03730 text_log->PushIndent();
03731 text_log->Print("edge.m_ti[%d]=%d (should be >=0 and <%d=m_T.Count())\n",eti,ti);
03732 text_log->PopIndent();
03733 }
03734 return ON_BrepIsNotValid();
03735 }
03736 if ( m_T[ti].m_trim_index != ti )
03737 {
03738 if ( text_log )
03739 {
03740 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03741 text_log->PushIndent();
03742 text_log->Print("edge.m_ti[%d]=%d is a deleted trim\n",eti,ti);
03743 text_log->PopIndent();
03744 }
03745 return ON_BrepIsNotValid();
03746 }
03747 for ( i = 0; i < eti; i++ )
03748 {
03749 if ( edge.m_ti[i] == ti )
03750 {
03751 if ( text_log )
03752 {
03753 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03754 text_log->PushIndent();
03755 text_log->Print("edge.m_ti[%d]=edge.m_ti[%d]=%d (a trim should be referenced once).\n",i,eti,ti);
03756 text_log->PopIndent();
03757 }
03758 return ON_BrepIsNotValid();
03759 }
03760 }
03761 const ON_BrepTrim& trim = m_T[ti];
03762 if ( trim.m_ei != edge_index )
03763 {
03764 if ( text_log )
03765 {
03766 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03767 text_log->PushIndent();
03768 text_log->Print("edge.m_ti[%d]=%d but brep.m_T[%d].m_ei=%d\n",eti,ti,ti,trim.m_ei);
03769 text_log->PopIndent();
03770 }
03771 return ON_BrepIsNotValid();
03772 }
03773 }
03774
03775 if ( edge.m_tolerance < 0.0 )
03776 {
03777 if ( text_log )
03778 {
03779 text_log->Print("brep.m_E[%d] edge is not valid.\n",edge_index);
03780 text_log->PushIndent();
03781 text_log->Print("edge.m_tolerance=%g (should be >= 0.0)\n",edge.m_tolerance);
03782 text_log->PopIndent();
03783 }
03784 return ON_BrepIsNotValid();
03785 }
03786
03787 return true;
03788 }
03789
03790 bool
03791 ON_Brep::IsValidVertex( int vertex_index, ON_TextLog* text_log ) const
03792 {
03793 if ( vertex_index < 0 || vertex_index >= m_V.Count() )
03794 {
03795 if ( text_log )
03796 text_log->Print("brep vertex_index = %d (should be >=0 and <%d=brep.m_V.Count() ).\n",
03797 vertex_index, m_V.Count());
03798 return ON_BrepIsNotValid();
03799 }
03800 const ON_BrepVertex& vertex = m_V[vertex_index];
03801 if ( vertex.m_vertex_index != vertex_index )
03802 {
03803 if ( text_log )
03804 {
03805 text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
03806 text_log->PushIndent();
03807 text_log->Print("vertex.m_vertex_index = %d (should be %d).\n",
03808 vertex.m_vertex_index, vertex_index );
03809 text_log->PopIndent();
03810 }
03811 return ON_BrepIsNotValid();
03812 }
03813
03814 const int vertex_edge_count = vertex.m_ei.Count();
03815 int i, j, vei, ei;
03816 for ( vei = 0; vei < vertex_edge_count; vei++ ) {
03817 ei = vertex.m_ei[vei];
03818 if ( ei < 0 || ei >= m_E.Count() )
03819 {
03820 if ( text_log )
03821 {
03822 text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
03823 text_log->PushIndent();
03824 text_log->Print("vertex.m_ei[%d] = %d (should be >=0 and <%d).\n", vei, ei, m_E.Count());
03825 text_log->PopIndent();
03826 }
03827 return ON_BrepIsNotValid();
03828 }
03829 const ON_BrepEdge& edge = m_E[ei];
03830 if ( ei != edge.m_edge_index )
03831 {
03832 if ( text_log )
03833 {
03834 text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
03835 text_log->PushIndent();
03836 text_log->Print("vertex.m_ei[%d] = %d is a deleted edge.\n", vei, ei);
03837 text_log->PopIndent();
03838 }
03839 return ON_BrepIsNotValid();
03840 }
03841 for ( i = 0; i < vei; i++ )
03842 {
03843 if ( vertex.m_ei[i] == ei )
03844 {
03845
03846 if ( edge.m_vi[0] != vertex_index || edge.m_vi[1] != vertex_index )
03847 {
03848 if ( text_log )
03849 {
03850 text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
03851 text_log->PushIndent();
03852 text_log->Print("vertex.m_ei[%d] and vertex.m_ei[%d] = %d but brep.m_E[%d].m_vi[0] = %d",
03853 i,vei,ei,ei,edge.m_vi[0]);
03854 text_log->Print("and ON_Brep.m_E[%d].m_vi[1] = %d (both m_vi[] values should be %d).\n",
03855 ei,edge.m_vi[1],vertex_index);
03856 text_log->PopIndent();
03857 }
03858 return ON_BrepIsNotValid();
03859 }
03860 for (j = i+1; j < vei; j++ )
03861 {
03862 if ( vertex.m_ei[j] == ei )
03863 {
03864 if ( text_log )
03865 {
03866 text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
03867 text_log->PushIndent();
03868 text_log->Print("vertex.m_ei[%d,%d,%d] = %d. An open edge index should appear once\n",i,vei,j,ei);
03869 text_log->Print("in vertex.m_ei[] and a closed edge index should appear twice.\n");
03870 text_log->PopIndent();
03871 }
03872 return ON_BrepIsNotValid();
03873 }
03874 }
03875 break;
03876 }
03877 }
03878 if ( edge.m_vi[0] != vertex_index && edge.m_vi[1] != vertex_index )
03879 {
03880 if ( text_log )
03881 {
03882 text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
03883 text_log->PushIndent();
03884 text_log->Print("vertex.m_ei[%d] = %d but ON_Brep.m_E[%d].m_vi[] = [%d,%d]. "
03885 "At least one edge m_vi[] value should be %d.\n",
03886 vei,ei,ei,edge.m_vi[0],edge.m_vi[1],vertex_index);
03887 text_log->PopIndent();
03888 }
03889 return ON_BrepIsNotValid();
03890 }
03891 }
03892
03893 if ( vertex.m_tolerance < 0.0 )
03894 {
03895 if ( text_log )
03896 {
03897 text_log->Print("brep.m_V[%d] vertex is not valid.\n",vertex_index);
03898 text_log->PushIndent();
03899 text_log->Print("vertex.m_tolerace = %g (should be >= 0.0)\n",vertex.m_tolerance);
03900 text_log->PopIndent();
03901 }
03902 return ON_BrepIsNotValid();
03903 }
03904 return true;
03905 }
03906
03907
03908
03909 static
03910 bool TestTrimPBox( const ON_BrepTrim& trim, ON_TextLog* text_log )
03911 {
03912 ON_3dPoint pt;
03913 double d;
03914 ON_BoundingBox pbox = trim.m_pbox;
03915
03916
03917 d = ON_SQRT_EPSILON*(fabs(pbox.m_min.x)+fabs(pbox.m_max.x));
03918 if ( d < ON_ZERO_TOLERANCE )
03919 d = ON_ZERO_TOLERANCE;
03920 pbox.m_min.x -= d;
03921 pbox.m_max.x += d;
03922
03923 d = ON_SQRT_EPSILON*(fabs(pbox.m_min.y)+fabs(pbox.m_max.y));
03924 if ( d < ON_ZERO_TOLERANCE )
03925 d = ON_ZERO_TOLERANCE;
03926 pbox.m_min.y -= d;
03927 pbox.m_max.y += d;
03928
03929 pt = trim.PointAtStart();
03930 if ( !pbox.IsPointIn(pt) )
03931 {
03932 if ( text_log )
03933 text_log->Print("ON_Brep.m_T[%d].m_pbox does not contain start of trim.\n",trim.m_trim_index);
03934 return false;
03935 }
03936
03937 pt = trim.PointAtEnd();
03938
03939 if ( !pbox.IsPointIn(pt) )
03940 {
03941 if ( text_log )
03942 text_log->Print("ON_Brep.m_T[%d].m_pbox does not contain end of trim.\n",trim.m_trim_index);
03943 return false;
03944 }
03945
03946 pt = trim.PointAt(trim.Domain().ParameterAt(0.5));
03947 if ( !pbox.IsPointIn(pt) )
03948 {
03949 if ( text_log )
03950 text_log->Print("ON_Brep.m_T[%d].m_pbox does not contain middle of trim.\n",trim.m_trim_index);
03951 return false;
03952 }
03953
03954 return true;
03955 }
03956
03957 static
03958 bool CheckTrimOnSrfHelper( const ON_Interval& srf_domain0,
03959 const ON_Interval& srf_domain1,
03960 const ON_BrepTrim& trim,
03961 ON_TextLog* text_log
03962 )
03963 {
03964
03965 const ON_BrepTrimPoint* tp = trim.m_pline.Array();
03966 int i, count = trim.m_pline.Count();
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991 const double a = -0.01;
03992 const double b = 1.01;
03993
03994 double s,t;
03995 for ( i = 0; i < count; i++ )
03996 {
03997 s = srf_domain0.NormalizedParameterAt(tp[i].p.x);
03998 t = srf_domain1.NormalizedParameterAt(tp[i].p.y);
03999 if ( s < a || s > b || t < a || t > b )
04000 {
04001 if ( text_log )
04002 {
04003 text_log->Print("ON_Brep.m_T[%d] 2d curve is not inside surface domain.\n",trim.m_trim_index);
04004 }
04005 return false;
04006 }
04007 }
04008 return true;
04009 }
04010
04011 static
04012 bool CheckLoopOnSrfHelper( const ON_Brep& brep,
04013 const ON_Interval& srf_domain0,
04014 const ON_Interval& srf_domain1,
04015 const ON_BrepLoop& loop,
04016 ON_TextLog* text_log
04017 )
04018 {
04019 for ( int lti = 0; lti < loop.m_ti.Count(); lti++ )
04020 {
04021 int ti = loop.m_ti[lti];
04022 if ( ti < 0 || ti >= brep.m_T.Count() )
04023 continue;
04024 if ( ! CheckTrimOnSrfHelper( srf_domain0, srf_domain1, brep.m_T[ti], text_log ) )
04025 return false;
04026 }
04027 return true;
04028 }
04029
04030 ON_BOOL32
04031 ON_Brep::IsValid( ON_TextLog* text_log ) const
04032 {
04033 const int curve2d_count = m_C2.Count();
04034 const int curve3d_count = m_C3.Count();
04035 const int surface_count = m_S.Count();
04036 const int vertex_count = m_V.Count();
04037 const int edge_count = m_E.Count();
04038 const int trim_count = m_T.Count();
04039 const int loop_count = m_L.Count();
04040 const int face_count = m_F.Count();
04041
04042 int c2i, c3i, si, vi, ei, fi, ti, li;
04043
04044 if ( 0 == face_count && 0 == edge_count && 0 == vertex_count )
04045 {
04046 if ( text_log )
04047 text_log->Print( "ON_Brep has no faces, edges, or vertices\n");
04048 return ON_BrepIsNotValid();
04049 }
04050
04051 if ( 0 != face_count )
04052 {
04053 if ( 0 == edge_count )
04054 {
04055 if ( text_log )
04056 text_log->Print( "ON_Brep has no edges.\n");
04057 return ON_BrepIsNotValid();
04058 }
04059 if ( 0 == loop_count )
04060 {
04061 if ( text_log )
04062 text_log->Print( "ON_Brep has no loops.\n");
04063 return ON_BrepIsNotValid();
04064 }
04065 if ( 0 == surface_count )
04066 {
04067 if ( text_log )
04068 text_log->Print( "ON_Brep has no surfaces.\n");
04069 return ON_BrepIsNotValid();
04070 }
04071 if ( 0 == trim_count )
04072 {
04073 if ( text_log )
04074 text_log->Print( "ON_Brep has no trims.\n");
04075 return ON_BrepIsNotValid();
04076 }
04077 if ( 0 == curve2d_count )
04078 {
04079 if ( text_log )
04080 text_log->Print( "ON_Brep has no 2d curves.\n");
04081 return ON_BrepIsNotValid();
04082 }
04083 }
04084
04085 if ( 0 != edge_count )
04086 {
04087 if ( 0 == curve3d_count )
04088 {
04089 if ( text_log )
04090 text_log->Print( "ON_Brep has no 3d curves.\n");
04091 return ON_BrepIsNotValid();
04092 }
04093 if ( 0 == vertex_count )
04094 {
04095 if ( text_log )
04096 text_log->Print( "ON_Brep has no vertices.\n");
04097 return ON_BrepIsNotValid();
04098 }
04099 }
04100
04101
04102 for ( vi = 0; vi < vertex_count; vi++ )
04103 {
04104 if ( m_V[vi].m_vertex_index == -1 )
04105 {
04106 const ON_BrepVertex& vertex = m_V[vi];
04107 if ( vertex.m_ei.Count() > 0 )
04108 {
04109 if ( text_log )
04110 text_log->Print( "ON_Brep.m_V[%d] is deleted (m_vertex_index = -1) but vertex.m_ei.Count() = %d.\n",
04111 vi, vertex.m_ei.Count() );
04112 return ON_BrepIsNotValid();
04113 }
04114 }
04115 else if ( m_V[vi].m_vertex_index != vi )
04116 {
04117 if ( text_log )
04118 text_log->Print( "ON_Brep.m_V[%d].m_vertex_index = %d (should be %d)\n",
04119 vi, m_V[vi].m_vertex_index, vi );
04120 return ON_BrepIsNotValid();
04121 }
04122 }
04123
04124 for ( ei = 0; ei < edge_count; ei++ )
04125 {
04126 if ( m_E[ei].m_edge_index == -1 )
04127 {
04128 const ON_BrepEdge& edge = m_E[ei];
04129 if ( edge.m_ti.Count() > 0 )
04130 {
04131 if ( text_log )
04132 text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_ti.Count() = %d.\n",
04133 ei, edge.m_ti.Count() );
04134 return ON_BrepIsNotValid();
04135 }
04136 if ( edge.m_c3i != -1 )
04137 {
04138 if ( text_log )
04139 text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_c3i=%d (should be -1).\n",
04140 ei, edge.m_c3i );
04141 return ON_BrepIsNotValid();
04142 }
04143 if ( edge.ProxyCurve() )
04144 {
04145 if ( text_log )
04146 text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_curve is not NULL.\n",
04147 ei );
04148 return ON_BrepIsNotValid();
04149 }
04150 if ( edge.m_vi[0] != -1 )
04151 {
04152 if ( text_log )
04153 text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_vi[0]=%d (should be -1).\n",
04154 ei, edge.m_vi[0] );
04155 return ON_BrepIsNotValid();
04156 }
04157 if ( edge.m_vi[1] != -1 )
04158 {
04159 if ( text_log )
04160 text_log->Print( "ON_Brep.m_E[%d] is deleted (m_edge_index = -1) but edge.m_vi[1]=%d (should be -1).\n",
04161 ei, edge.m_vi[1] );
04162 return ON_BrepIsNotValid();
04163 }
04164 }
04165 else if ( m_E[ei].m_edge_index != ei )
04166 {
04167 if ( text_log )
04168 text_log->Print( "ON_Brep.m_E[%d].m_edge_index = %d (should be %d)\n",
04169 ei, m_E[ei].m_edge_index, ei );
04170 return ON_BrepIsNotValid();
04171 }
04172 }
04173
04174 for ( ti = 0; ti < trim_count; ti++ )
04175 {
04176 if ( m_T[ti].m_trim_index == -1 )
04177 {
04178 const ON_BrepTrim& trim = m_T[ti];
04179 if ( trim.m_ei != -1 )
04180 {
04181 if ( text_log )
04182 text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_ei=%d (should be -1).\n",
04183 ti, trim.m_ei );
04184 return ON_BrepIsNotValid();
04185 }
04186 if ( trim.m_li != -1 )
04187 {
04188 if ( text_log )
04189 text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_li=%d (should be -1).\n",
04190 ti, trim.m_li );
04191 return ON_BrepIsNotValid();
04192 }
04193 if ( trim.m_c2i != -1 )
04194 {
04195 if ( text_log )
04196 text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_c2i=%d (should be -1).\n",
04197 ti, trim.m_c2i );
04198 return ON_BrepIsNotValid();
04199 }
04200 if ( trim.m_vi[0] != -1 )
04201 {
04202 if ( text_log )
04203 text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_vi[0]=%d (should be -1).\n",
04204 ti, trim.m_vi[0] );
04205 return ON_BrepIsNotValid();
04206 }
04207 if ( trim.m_vi[1] != -1 )
04208 {
04209 if ( text_log )
04210 text_log->Print( "ON_Brep.m_T[%d] is deleted (m_trim_index = -1) but trim.m_vi[1]=%d (should be -1).\n",
04211 ti, trim.m_vi[1] );
04212 return ON_BrepIsNotValid();
04213 }
04214 }
04215 else if ( m_T[ti].m_trim_index != ti )
04216 {
04217 if ( text_log )
04218 text_log->Print( "ON_Brep.m_T[%d].m_trim_index = %d (should be %d)\n",
04219 ti, m_T[ti].m_trim_index, ti );
04220 return ON_BrepIsNotValid();
04221 }
04222 else if ( !m_T[ti].IsValid( text_log ) )
04223 {
04224 if ( text_log )
04225 text_log->Print( "ON_Brep.m_T[%d] is not valid\n",ti );
04226 return ON_BrepIsNotValid();
04227 }
04228 }
04229
04230 for ( li = 0; li < loop_count; li++ )
04231 {
04232 if ( m_L[li].m_loop_index == -1 )
04233 {
04234 const ON_BrepLoop& loop = m_L[li];
04235 if ( loop.m_fi != -1 )
04236 {
04237 if ( text_log )
04238 text_log->Print( "ON_Brep.m_L[%d] is deleted (m_loop_index = -1) but loop.m_fi=%d (should be -1).\n",
04239 li, loop.m_fi );
04240 return ON_BrepIsNotValid();
04241 }
04242 if ( loop.m_ti.Count() > 0 )
04243 {
04244 if ( text_log )
04245 text_log->Print( "ON_Brep.m_L[%d] is deleted (m_loop_index = -1) but loop.m_ti.Count()=%d.\n",
04246 li, loop.m_ti.Count() );
04247 return ON_BrepIsNotValid();
04248 }
04249 }
04250 else if ( m_L[li].m_loop_index != li )
04251 {
04252 if ( text_log )
04253 text_log->Print( "ON_Brep.m_L[%d].m_loop_index = %d (should be %d)\n",
04254 li, m_L[li].m_loop_index, li );
04255 return ON_BrepIsNotValid();
04256 }
04257 }
04258
04259 for ( fi = 0; fi < face_count; fi++ )
04260 {
04261 if ( m_F[fi].m_face_index == -1 )
04262 {
04263 const ON_BrepFace& face = m_F[fi];
04264 if ( face.m_si != -1 )
04265 {
04266 if ( text_log )
04267 text_log->Print( "ON_Brep.m_F[%d] is deleted (m_face_index = -1) but face.m_si=%d (should be -1).\n",
04268 fi, face.m_si );
04269 return ON_BrepIsNotValid();
04270 }
04271 if ( face.ProxySurface() )
04272 {
04273 if ( text_log )
04274 text_log->Print( "ON_Brep.m_F[%d] is deleted (m_face_index = -1) but face.ProxySurface() is not NULL.\n",
04275 fi );
04276 return ON_BrepIsNotValid();
04277 }
04278 if ( face.m_li.Count() > 0 )
04279 {
04280 if ( text_log )
04281 text_log->Print( "ON_Brep.m_F[%d] is deleted (m_face_index = -1) but face.m_li.Count()=%d.\n",
04282 fi, face.m_li.Count() );
04283 return ON_BrepIsNotValid();
04284 }
04285 }
04286 else if ( m_F[fi].m_face_index != fi )
04287 {
04288 if ( text_log )
04289 text_log->Print( "ON_Brep.m_F[%d].m_face_index = %d (should be %d)\n",
04290 fi, m_F[fi].m_face_index, fi );
04291 return ON_BrepIsNotValid();
04292 }
04293 }
04294
04295
04296 for ( c2i = 0; c2i < curve2d_count; c2i++ ) {
04297 if ( !m_C2[c2i] )
04298 {
04299 continue;
04300
04301
04302
04303
04304 }
04305 if ( !m_C2[c2i]->IsValid(text_log) )
04306 {
04307 if ( text_log )
04308 text_log->Print("ON_Brep.m_C2[%d] is invalid.\n",c2i);
04309 return ON_BrepIsNotValid();
04310 }
04311 int c2_dim = m_C2[c2i]->Dimension();
04312 if ( c2_dim != 2 )
04313 {
04314 if ( text_log )
04315 text_log->Print("ON_Brep.m_C2[%d]->Dimension() = %d (should be 2).\n", c2i, c2_dim );
04316 return ON_BrepIsNotValid();
04317 }
04318 const ON_PolyCurve* polycurve = ON_PolyCurve::Cast(m_C2[c2i]);
04319 if ( polycurve && polycurve->IsNested() )
04320 {
04321 if ( text_log )
04322 text_log->Print("ON_Brep.m_C2[%d] is a nested polycurve.\n", c2i );
04323 return ON_BrepIsNotValid();
04324 }
04325 }
04326
04327
04328 for ( c3i = 0; c3i < curve3d_count; c3i++ ) {
04329 if ( !m_C3[c3i] )
04330 {
04331 continue;
04332
04333
04334
04335
04336 }
04337 if ( !m_C3[c3i]->IsValid(text_log) )
04338 {
04339 if ( text_log )
04340 text_log->Print("ON_Brep.m_C3[%d] is invalid.\n",c3i);
04341 return ON_BrepIsNotValid();
04342 }
04343 int c3_dim = m_C3[c3i]->Dimension();
04344 if ( c3_dim != 3 )
04345 {
04346 if ( text_log )
04347 text_log->Print("ON_Brep.m_C3[%d]->Dimension() = %d (should be 3).\n", c3i, c3_dim );
04348 return ON_BrepIsNotValid();
04349 }
04350 const ON_PolyCurve* polycurve = ON_PolyCurve::Cast(m_C3[c3i]);
04351 if ( polycurve && polycurve->IsNested() )
04352 {
04353 if ( text_log )
04354 text_log->Print("ON_Brep.m_C3[%d] is a nested polycurve.\n", c3i );
04355 return ON_BrepIsNotValid();
04356 }
04357 }
04358
04359
04360 for ( si = 0; si < surface_count; si++ ) {
04361 if ( !m_S[si] )
04362 {
04363 continue;
04364
04365
04366
04367
04368 }
04369 if ( !m_S[si]->IsValid(text_log) )
04370 {
04371 if ( text_log )
04372 text_log->Print("ON_Brep.m_S[%d] is invalid.\n",si);
04373 return ON_BrepIsNotValid();
04374 }
04375 int dim = m_S[si]->Dimension();
04376 if ( dim != 3 )
04377 {
04378 if ( text_log )
04379 text_log->Print("ON_Brep.m_S[%d]->Dimension() = %d (should be 3).\n", si, dim );
04380 return ON_BrepIsNotValid();
04381 }
04382 }
04383
04384
04385 for ( vi = 0; vi < vertex_count; vi++ ) {
04386 if ( m_V[vi].m_vertex_index == -1 )
04387 continue;
04388 if ( !IsValidVertex( vi, text_log ) ) {
04389 if ( text_log )
04390 text_log->Print("ON_Brep.m_V[%d] is invalid.\n",vi);
04391 return ON_BrepIsNotValid();
04392 }
04393 }
04394
04395
04396 for ( ei = 0; ei < edge_count; ei++ )
04397 {
04398 if ( m_E[ei].m_edge_index == -1 )
04399 continue;
04400 if ( !IsValidEdge( ei, text_log ) ) {
04401 if ( text_log )
04402 text_log->Print("ON_Brep.m_E[%d] is invalid.\n",ei);
04403 return ON_BrepIsNotValid();
04404 }
04405 }
04406
04407
04408 for ( fi = 0; fi < face_count; fi++ )
04409 {
04410 if ( m_F[fi].m_face_index == -1 )
04411 continue;
04412 if ( !IsValidFace( fi, text_log ) ) {
04413 if ( text_log )
04414 text_log->Print("ON_Brep.m_F[%d] is invalid.\n",fi);
04415 return ON_BrepIsNotValid();
04416 }
04417 }
04418
04419
04420
04421
04422
04423
04424 for ( li = 0; li < loop_count; li++ )
04425 {
04426 const ON_BrepLoop& loop = m_L[li];
04427 if ( m_L[li].m_loop_index == -1 )
04428 continue;
04429 if ( loop.m_fi < 0 || loop.m_fi >= m_F.Count() )
04430 {
04431 if ( text_log )
04432 text_log->Print("ON_Brep.m_L[%d].m_fi = %d is not invalid.\n",li,loop.m_fi);
04433 return ON_BrepIsNotValid();
04434 }
04435 if ( m_F[loop.m_fi].m_face_index != loop.m_fi )
04436 {
04437 if ( text_log )
04438 text_log->Print("ON_Brep.m_L[%d].m_fi = %d is a deleted face.\n",li,loop.m_fi);
04439 return ON_BrepIsNotValid();
04440 }
04441
04442
04443
04444
04445
04446 for ( int lti = 0; lti < loop.m_ti.Count(); lti++ )
04447 {
04448 ti = loop.m_ti[lti];
04449 if ( ti < 0 || ti >= m_T.Count() )
04450 {
04451 if ( text_log )
04452 text_log->Print("ON_Brep.m_L[%d].m_ti[%d] = %d is not invalid.\n",li,lti,ti);
04453 return ON_BrepIsNotValid();
04454 }
04455 if ( m_T[ti].m_trim_index != ti )
04456 {
04457 if ( text_log )
04458 text_log->Print("ON_Brep.m_L[%d].m_ti[%d] = %d is a deleted trim.\n",li,lti,ti);
04459 return ON_BrepIsNotValid();
04460 }
04461 }
04462 }
04463
04464
04465
04466
04467
04468
04469 int seam_trim_count = 0;
04470 for ( ti = 0; ti < trim_count; ti++ )
04471 {
04472 const ON_BrepTrim& trim = m_T[ti];
04473 if ( trim.m_trim_index == -1 )
04474 continue;
04475
04476 if ( trim.m_vi[0] < 0 || trim.m_vi[0] >= m_V.Count() )
04477 {
04478 if ( text_log )
04479 text_log->Print("ON_Brep.m_T[%d].m_vi[0] = %d is not invalid.\n",ti,trim.m_vi[0]);
04480 return ON_BrepIsNotValid();
04481 }
04482 if ( trim.m_vi[1] < 0 || trim.m_vi[1] >= m_V.Count() )
04483 {
04484 if ( text_log )
04485 text_log->Print("ON_Brep.m_T[%d].m_vi[1] = %d is not invalid.\n",ti,trim.m_vi[1]);
04486 return ON_BrepIsNotValid();
04487 }
04488
04489 if ( m_V[trim.m_vi[0]].m_vertex_index != trim.m_vi[0] )
04490 {
04491 if ( text_log )
04492 text_log->Print("ON_Brep.m_T[%d].m_vi[0] is deleted.\n",ti);
04493 return ON_BrepIsNotValid();
04494 }
04495 if ( m_V[trim.m_vi[1]].m_vertex_index != trim.m_vi[1] )
04496 {
04497 if ( text_log )
04498 text_log->Print("ON_Brep.m_T[%d].m_vi[1] is deleted.\n",ti);
04499 return ON_BrepIsNotValid();
04500 }
04501
04502 if ( trim.m_c2i < 0 || trim.m_c2i >= m_C2.Count() )
04503 {
04504 if ( text_log )
04505 text_log->Print("ON_Brep.m_T[%d].m_c2i = %d is not valid.\n",ti,trim.m_c2i);
04506 return ON_BrepIsNotValid();
04507 }
04508
04509 if ( 0 == m_C2[trim.m_c2i] )
04510 {
04511 if ( text_log )
04512 text_log->Print("ON_Brep.m_T[%d].m_c2i = %d, but m_C2[%d] is NULL.\n",ti,trim.m_c2i,trim.m_c2i);
04513 return ON_BrepIsNotValid();
04514 }
04515
04516 if ( trim.m_li < 0 || trim.m_li >= m_L.Count() )
04517 {
04518 if ( text_log )
04519 text_log->Print("ON_Brep.m_T[%d].m_li = %d is not valid.\n",ti,trim.m_li);
04520 return ON_BrepIsNotValid();
04521 }
04522
04523 if ( m_L[trim.m_li].m_loop_index != trim.m_li )
04524 {
04525 if ( text_log )
04526 text_log->Print("ON_Brep.m_T[%d].m_li = %d is a deleted loop.\n",ti,trim.m_li);
04527 return ON_BrepIsNotValid();
04528 }
04529
04530 {
04531 const ON_Curve* c2 = m_C2[trim.m_c2i];
04532 const ON_Surface* srf = m_S[m_F[m_L[trim.m_li].m_fi].m_si];
04533 if ( srf )
04534 {
04535 ON_Interval PD = trim.ProxyCurveDomain();
04536 ON_Surface::ISO iso = srf->IsIsoparametric(*c2, &PD);
04537 if ( trim.m_iso != iso )
04538 {
04539 if ( text_log )
04540 text_log->Print("ON_Brep.m_T[%d].m_iso = %d and it should be %d\n",ti,trim.m_iso,iso);
04541 return ON_BrepIsNotValid();
04542 }
04543 }
04544 }
04545
04546 if ( trim.m_type == ON_BrepTrim::singular )
04547 {
04548 if ( trim.m_ei != -1 )
04549 {
04550 if ( text_log )
04551 text_log->Print("ON_Brep.m_T[%d].m_type = singular, but m_ei = %d (should be -1).\n",ti,trim.m_ei);
04552 return ON_BrepIsNotValid();
04553 }
04554 continue;
04555 }
04556
04557 if ( trim.m_ei < 0 || trim.m_ei >= m_E.Count() )
04558 {
04559 if ( text_log )
04560 text_log->Print("ON_Brep.m_T[%d].m_ei = %d is not invalid.\n",ti,trim.m_ei);
04561 return ON_BrepIsNotValid();
04562 }
04563
04564 const ON_BrepEdge& edge = m_E[trim.m_ei];
04565 if ( edge.m_edge_index != trim.m_ei )
04566 {
04567 if ( text_log )
04568 text_log->Print("ON_Brep.m_T[%d].m_ei is deleted.\n",ti);
04569 return ON_BrepIsNotValid();
04570 }
04571
04572 const int evi0 = trim.m_bRev3d ? 1 : 0;
04573 const int evi1 = trim.m_bRev3d ? 0 : 1;
04574 if ( trim.m_vi[0] != edge.m_vi[evi0] )
04575 {
04576 if ( text_log )
04577 text_log->Print("ON_Brep.m_T[%d].m_bRev3d = %d, but m_vi[0] != m_E[m_ei].m_vi[%d].\n",ti,trim.m_bRev3d,evi0);
04578 return ON_BrepIsNotValid();
04579 }
04580 if ( trim.m_vi[1] != edge.m_vi[evi1] )
04581 {
04582 if ( text_log )
04583 text_log->Print("ON_Brep.m_T[%d].m_bRev3d = %d, but m_vi[0] != m_E[m_ei].m_vi[%d].\n",ti,trim.m_bRev3d,evi1);
04584 return ON_BrepIsNotValid();
04585 }
04586
04587
04588 {
04589 ON_3dPoint trim_pt0, trim_pt1, srf_pt0, srf_pt1;
04590 ON_3dVector trim_der0, trim_der1, srf_du0, srf_dv0, srf_du1, srf_dv1;
04591 ON_Interval trim_domain = trim.Domain();
04592
04593
04594
04595
04596
04597 trim.Ev1Der( trim_domain[0], trim_pt0, trim_der0 );
04598 trim.Ev1Der( trim_domain[1], trim_pt1, trim_der1 );
04599
04600 const ON_Surface* trim_srf = m_F[ m_L[trim.m_li].m_fi ].SurfaceOf();
04601 trim_srf->Ev1Der( trim_pt0.x, trim_pt0.y, srf_pt0, srf_du0, srf_dv0 );
04602 trim_srf->Ev1Der( trim_pt1.x, trim_pt1.y, srf_pt1, srf_du1, srf_dv1 );
04603
04604
04605 double t0_tol = srf_du0.Length()*trim.m_tolerance[0] + srf_dv0.Length()*trim.m_tolerance[1];
04606 double t1_tol = srf_du1.Length()*trim.m_tolerance[0] + srf_dv1.Length()*trim.m_tolerance[1];
04607 ON_3dVector trim_tangent0 = trim_der0.x*srf_du0 + trim_der0.y*srf_dv0;
04608 trim_tangent0.Unitize();
04609 ON_3dVector trim_tangent1 = trim_der1.x*srf_du1 + trim_der1.y*srf_dv1;
04610 trim_tangent1.Unitize();
04611 ON_3dVector edge_tangent0 = edge.TangentAt( edge.Domain()[trim.m_bRev3d ? 1 : 0] );
04612 ON_3dVector edge_tangent1 = edge.TangentAt( edge.Domain()[trim.m_bRev3d ? 0 : 1] );
04613 double d0 = trim_tangent0*edge_tangent0;
04614 double d1 = trim_tangent1*edge_tangent1;
04615 if ( trim.m_bRev3d )
04616 {
04617 d0 = -d0;
04618 d1 = -d1;
04619 }
04620 if ( trim.m_vi[0] == trim.m_vi[1]
04621 && edge.m_vi[0] == edge.m_vi[1]
04622 && trim.m_vi[0] == edge.m_vi[0]
04623 )
04624 {
04625
04626
04627
04628
04629
04630 if ( d0 < 0.0 || d1 < 0.0)
04631 {
04632 if ( text_log )
04633 {
04634 if ( trim.m_bRev3d )
04635 text_log->Print("ON_Brep.m_T[%d].m_bRev3d = true, but closed curve directions are the same.\n",ti);
04636 else
04637 text_log->Print("ON_Brep.m_T[%d].m_bRev3d = false, but closed curve directions are opposite.\n",ti);
04638 }
04639 return ON_BrepIsNotValid();
04640 }
04641 }
04642
04643
04644 ON_3dPoint EdgeEnd[2];
04645 EdgeEnd[trim.m_bRev3d?1:0] = edge.PointAtStart();
04646 EdgeEnd[trim.m_bRev3d?0:1] = edge.PointAtEnd();
04647 d0 = EdgeEnd[0].DistanceTo(srf_pt0);
04648 d1 = EdgeEnd[1].DistanceTo(srf_pt1);
04649 double etol = edge.m_tolerance;
04650 double dtol = 10.0*(etol + t0_tol + t1_tol);
04651 if ( dtol < 0.01 )
04652 dtol = 0.01;
04653 if ( d0 > dtol )
04654 {
04655 if ( text_log )
04656 {
04657 text_log->Print("Distance from start of ON_Brep.m_T[%d] to 3d edge is %g. (edge tol = %g, trim tol ~ %g).\n",
04658 ti, d0, etol,t0_tol);
04659 }
04660 return ON_BrepIsNotValid();
04661 }
04662 if ( d1 > dtol )
04663 {
04664 if ( text_log )
04665 {
04666 text_log->Print("Distance from end of ON_Brep.m_T[%d] to 3d edge is %g. (edge tol = %g, trim tol ~ %g).\n",
04667 ti, d1, etol,t1_tol);
04668 }
04669 return ON_BrepIsNotValid();
04670 }
04671 }
04672
04673
04674 {
04675 if ( trim.m_pbox.m_min.z != 0.0 )
04676 {
04677 if ( text_log )
04678 text_log->Print("ON_Brep.m_T[%d].m_pbox.m_min.z = %g (should be zero).\n",ti,trim.m_pbox.m_min.z);
04679 return ON_BrepIsNotValid();
04680 }
04681 if ( trim.m_pbox.m_max.z != 0.0 )
04682 {
04683 if ( text_log )
04684 text_log->Print("ON_Brep.m_T[%d].m_pbox.m_max.z = %g (should be zero).\n",ti,trim.m_pbox.m_max.z);
04685 return ON_BrepIsNotValid();
04686 }
04687
04688 if ( !TestTrimPBox( trim, text_log ) )
04689 return ON_BrepIsNotValid();
04690
04691 }
04692
04693 if ( ON_BrepTrim::seam == trim.m_type )
04694 {
04695
04696 switch ( trim.m_iso )
04697 {
04698 case ON_Surface::S_iso:
04699 break;
04700 case ON_Surface::E_iso:
04701 break;
04702 case ON_Surface::N_iso:
04703 break;
04704 case ON_Surface::W_iso:
04705 break;
04706 default:
04707 if ( text_log )
04708 text_log->Print("ON_Brep.m_T[%d].m_type = ON_BrepTrim::seam but m_iso is not N/E/W/S_iso.\n",ti);
04709 return ON_BrepIsNotValid();
04710 }
04711 seam_trim_count++;
04712 }
04713 }
04714
04715
04716 for ( li = 0; li < loop_count; li++ )
04717 {
04718 const ON_BrepLoop& loop = m_L[li];
04719 if ( loop.m_loop_index != li )
04720 continue;
04721 if ( loop.m_pbox.m_min.z != 0.0 )
04722 {
04723 if ( text_log )
04724 text_log->Print("ON_Brep.m_L[%d].m_pbox.m_min.z = %g (should be zero).\n",li,loop.m_pbox.m_min.z);
04725 return ON_BrepIsNotValid();
04726 }
04727 if ( loop.m_pbox.m_max.z != 0.0 )
04728 {
04729 if ( text_log )
04730 text_log->Print("ON_Brep.m_L[%d].m_pbox.m_max.z = %g (should be zero).\n",li,loop.m_pbox.m_max.z);
04731 return ON_BrepIsNotValid();
04732 }
04733 int first_trim_ti = -4;
04734 int first_trim_vi0 = -3;
04735 int prev_trim_vi1 = -2;
04736 int prev_trim_ti=-9;
04737 int lti;
04738 for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
04739 {
04740 const ON_BrepTrim& trim = m_T[loop.m_ti[lti]];
04741 if ( !loop.m_pbox.IsPointIn(trim.m_pbox.m_min) || !loop.m_pbox.IsPointIn(trim.m_pbox.m_max) )
04742 {
04743 if ( text_log )
04744 text_log->Print("ON_Brep.m_L[%d].m_pbox does not contain m_T[loop.m_ti[%d]].m_pbox.\n",li,lti);
04745 return ON_BrepIsNotValid();
04746 }
04747 if ( 0 == lti )
04748 {
04749 first_trim_ti = loop.m_ti[lti];
04750 first_trim_vi0 = trim.m_vi[0];
04751 }
04752 else if ( prev_trim_vi1 != trim.m_vi[0] )
04753 {
04754
04755
04756
04757 if ( text_log )
04758 text_log->Print("ON_Brep.m_L[%d] loop has trim vertex mismatch:\n m_T[loop.m_ti[%d]=%d].m_vi[1] = %d != m_T[loop.m_ti[%d]=%d].m_vi[0]=%d.\n",li,lti-1,prev_trim_ti,prev_trim_vi1,lti,loop.m_ti[lti],trim.m_vi[0]);
04759 return ON_BrepIsNotValid();
04760 }
04761 prev_trim_ti = loop.m_ti[lti];
04762 prev_trim_vi1 = trim.m_vi[1];
04763 }
04764
04765 if ( first_trim_ti >= 0 && first_trim_vi0 != prev_trim_vi1 )
04766 {
04767
04768
04769
04770 if ( text_log )
04771 text_log->Print("ON_Brep.m_L[%d] loop has trim vertex mismatch:\n m_T[loop.m_ti[%d]=%d].m_vi[1] = %d != m_T[loop.m_ti[%d]=%d].m_vi[0]=%d.\n",
04772 li,lti-1,prev_trim_ti,prev_trim_vi1,0,first_trim_ti,first_trim_vi0);
04773 return ON_BrepIsNotValid();
04774 }
04775 }
04776
04777
04778
04779
04780 ON_Interval srf_domain[2];
04781 for ( fi = 0; fi < face_count; fi++ )
04782 {
04783 const ON_BrepFace& face = m_F[fi];
04784 if ( face.m_face_index < 0 )
04785 continue;
04786 const ON_Surface* srf = m_S[face.m_si];
04787 if ( 0 == srf )
04788 continue;
04789
04790 srf_domain[0] = srf->Domain(0);
04791 srf_domain[1] = srf->Domain(1);
04792 for ( int fli = 0; fli < face.m_li.Count(); fli++ )
04793 {
04794 int li = face.m_li[fli];
04795 if ( li < 0 || li >= m_L.Count() )
04796 continue;
04797 if ( !CheckLoopOnSrfHelper(*this,srf_domain[0],srf_domain[1],m_L[li],text_log) )
04798 return ON_BrepIsNotValid();
04799 }
04800
04801 const ON_BrepLoop* outer_loop = face.OuterLoop();
04802 if ( 0 == outer_loop )
04803 continue;
04804
04805 ON_BOOL32 bClosed[2];
04806 bClosed[0] = srf->IsClosed(0);
04807 bClosed[1] = srf->IsClosed(1);
04808 if ( !bClosed[0] && !bClosed[1] )
04809 continue;
04810
04811 const int outer_trim_count = outer_loop->m_ti.Count();
04812 int lti, lti1;
04813 int endpt_index = 0;
04814 ON_Surface::ISO iso_type;
04815 ON_Interval side_interval;
04816 double s0, s1;
04817 const double side_tol = 1.0e-4;
04818
04819 for ( lti = 0; lti < outer_trim_count; lti++ )
04820 {
04821 const ON_BrepTrim& trim = m_T[outer_loop->m_ti[lti]];
04822 if ( ON_BrepTrim::boundary != trim.m_type )
04823 continue;
04824 if ( ON_Surface::E_iso == trim.m_iso && bClosed[0] )
04825 {
04826 iso_type = ON_Surface::W_iso;
04827 endpt_index = 1;
04828 }
04829 else if ( ON_Surface::W_iso == trim.m_iso && bClosed[0] )
04830 {
04831 iso_type = ON_Surface::E_iso;
04832 endpt_index = 1;
04833 }
04834 else if( ON_Surface::S_iso == trim.m_iso && bClosed[1] )
04835 {
04836 iso_type = ON_Surface::N_iso;
04837 endpt_index = 0;
04838 }
04839 else if( ON_Surface::N_iso == trim.m_iso && bClosed[1] )
04840 {
04841 iso_type = ON_Surface::S_iso;
04842 endpt_index = 0;
04843 }
04844 else
04845 continue;
04846
04847 side_interval.Set(trim.PointAtStart()[endpt_index],trim.PointAtEnd()[endpt_index]);
04848 if ( ON_Surface::N_iso == iso_type || ON_Surface::W_iso == iso_type )
04849 {
04850 if ( !side_interval.IsIncreasing() )
04851 continue;
04852 }
04853 else
04854 {
04855 if ( !side_interval.IsDecreasing() )
04856 continue;
04857 }
04858
04859
04860 for ( lti1 = 0; lti1 < outer_trim_count; lti1++ )
04861 {
04862 if ( lti1 == lti )
04863 continue;
04864 const ON_BrepTrim& trim1 = m_T[outer_loop->m_ti[lti1]];
04865 if ( iso_type != trim1.m_iso )
04866 continue;
04867 if ( ON_BrepTrim::boundary != trim1.m_type )
04868 continue;
04869
04870 s1 = side_interval.NormalizedParameterAt(trim1.PointAtStart()[endpt_index]);
04871 if ( fabs(s1-1.0) > side_tol )
04872 continue;
04873 s0 = side_interval.NormalizedParameterAt(trim1.PointAtEnd()[endpt_index]);
04874 if ( fabs(s0) > side_tol )
04875 continue;
04876
04877 if ( text_log )
04878 {
04879 text_log->Print("ON_Brep.m_F[%d] is on a closed surface. Outer loop m_L[%d] contains boundary trims %d and %d. They should be seam trims connected to the same edge.\n",
04880 face.m_face_index,outer_loop->m_loop_index,
04881 trim.m_trim_index,trim1.m_trim_index
04882 );
04883 }
04884 return ON_BrepIsNotValid();
04885 }
04886 }
04887 }
04888
04889
04890 for ( ti = 0; seam_trim_count > 0 && ti < trim_count; ti++ )
04891 {
04892 const ON_BrepTrim& trim = m_T[ti];
04893 if ( trim.m_trim_index == -1 )
04894 continue;
04895 if ( ON_BrepTrim::seam != trim.m_type )
04896 continue;
04897 seam_trim_count--;
04898 if ( trim.m_ei < 0 || trim.m_ei >= edge_count )
04899 {
04900 if ( text_log )
04901 {
04902 text_log->Print("ON_Brep.m_T[%d] is a seam trim with an invalid m_ei.\n",ti);
04903 return ON_BrepIsNotValid();
04904 }
04905 }
04906
04907 const ON_BrepEdge& edge = m_E[trim.m_ei];
04908 int trim1_index = -1;
04909 for ( int eti = 0; eti < edge.m_ti.Count(); eti++ )
04910 {
04911 const int ti1 = edge.m_ti[eti];
04912 if ( ti1 == ti
04913 || ti < 0
04914 || ti >= trim_count
04915 )
04916 {
04917 continue;
04918 }
04919 const ON_BrepTrim& trim1 = m_T[ti1];
04920 if ( trim1.m_trim_index == -1 )
04921 continue;
04922 if ( ON_BrepTrim::seam != trim1.m_type )
04923 continue;
04924 if ( trim1.m_li != trim.m_li )
04925 continue;
04926 if ( -1 == trim1_index )
04927 {
04928 trim1_index = ti1;
04929 continue;
04930 }
04931 text_log->Print("ON_Brep.m_T[%d,%d,%d] are three seam trims with the same edge in the same loop.\n",ti,trim1_index,ti1);
04932 return ON_BrepIsNotValid();
04933 }
04934
04935 if ( trim1_index < 0 || trim1_index >= trim_count )
04936 {
04937 text_log->Print("ON_Brep.m_T[%d] is a seam trim with no matching seam trim in the same loop.\n",ti);
04938 return ON_BrepIsNotValid();
04939 }
04940
04941
04942 switch(trim.m_iso)
04943 {
04944 case ON_Surface::S_iso:
04945 if ( ON_Surface::N_iso != m_T[trim1_index].m_iso )
04946 {
04947 if (text_log )
04948 text_log->Print("Seam trim ON_Brep.m_T[%d].m_iso = S_iso but matching seam ON_Brep.m_T[%d].m_iso != N_iso.\n",ti,trim1_index);
04949 return ON_BrepIsNotValid();
04950 }
04951 break;
04952
04953 case ON_Surface::E_iso:
04954 if ( ON_Surface::W_iso != m_T[trim1_index].m_iso )
04955 {
04956 if (text_log )
04957 text_log->Print("Seam trim ON_Brep.m_T[%d].m_iso = E_iso but matching seam ON_Brep.m_T[%d].m_iso != W_iso.\n",ti,trim1_index);
04958 return ON_BrepIsNotValid();
04959 }
04960 break;
04961
04962 case ON_Surface::N_iso:
04963 if ( ON_Surface::S_iso != m_T[trim1_index].m_iso )
04964 {
04965 if (text_log )
04966 text_log->Print("Seam trim ON_Brep.m_T[%d].m_iso = N_iso but matching seam ON_Brep.m_T[%d].m_iso != S_iso.\n",ti,trim1_index);
04967 return ON_BrepIsNotValid();
04968 }
04969 break;
04970
04971 case ON_Surface::W_iso:
04972 if ( ON_Surface::E_iso != m_T[trim1_index].m_iso )
04973 {
04974 if (text_log )
04975 text_log->Print("Seam trim ON_Brep.m_T[%d].m_iso = W_iso but matching seam ON_Brep.m_T[%d].m_iso != E_iso.\n",ti,trim1_index);
04976 return ON_BrepIsNotValid();
04977 }
04978 break;
04979
04980 case ON_Surface::not_iso:
04981 case ON_Surface::x_iso:
04982 case ON_Surface::y_iso:
04983 case ON_Surface::iso_count:
04984 break;
04985 }
04986
04987 }
04988
04989 #if 0
04990
04991 for ( ti = 0; ti < trim_count; ti++ )
04992 {
04993 const ON_BrepTrim& trim = m_T[ti];
04994 if ( trim.m_trim_index == -1 )
04995 continue;
04996 const int pline_count = trim.m_pline.Count();
04997 if ( 0 == pline_count )
04998 continue;
04999 if ( pline_count <= 1 )
05000 {
05001 if (text_log )
05002 text_log->Print("ON_Brep.m_T[%d].m_pline.Count() = 1. It should be 0 or >= 2\n",ti);
05003 return ON_BrepIsNotValid();
05004 }
05005
05006 const ON_Interval trim_domain = trim.Domain();
05007 if ( !(trim.m_pline[0].t == trim_domain[0]) )
05008 {
05009 if (text_log )
05010 text_log->Print("ON_Brep.m_T[%d].m_pline[0].t != start of trim domain.\n",ti);
05011 return ON_BrepIsNotValid();
05012 }
05013 if ( !(trim.m_pline[pline_count-1].t == trim_domain[1]) )
05014 {
05015 if (text_log )
05016 text_log->Print("ON_Brep.m_T[%d].m_pline[%d].t != end of trim domain.\n",ti,pline_count-1);
05017 return ON_BrepIsNotValid();
05018 }
05019 for ( int i = 1; i < pline_count; i++ )
05020 {
05021
05022 if ( !ON_IsValid(trim.m_pline[i].t) )
05023 {
05024 if (text_log )
05025 text_log->Print("ON_Brep.m_T[%d].m_pline[%d].t is not a valid double.\n",ti,i);
05026 return ON_BrepIsNotValid();
05027 }
05028 if ( !(trim.m_pline[i-1].t < trim.m_pline[i].t) )
05029 {
05030 if (text_log )
05031 text_log->Print("ON_Brep.m_T[%d].m_pline[%d].t must be < m_pline[%d].t.\n",ti,i-1,i);
05032 return ON_BrepIsNotValid();
05033 }
05034 }
05035
05036 if ( ON_UNSET_VALUE == trim.m_pline[0].e
05037 && ON_UNSET_VALUE == trim.m_pline[pline_count-1].e
05038 )
05039 {
05040
05041
05042
05043
05044
05045 continue;
05046 }
05047
05048 if ( trim.m_ei < 0 || trim.m_ei >= m_E.Count() )
05049 {
05050 if (text_log )
05051 text_log->Print("ON_Brep.m_T[%d].m_pline has e parameters but trim.m_ei is not valid.\n",ti);
05052 return ON_BrepIsNotValid();
05053 }
05054 const ON_BrepEdge& edge = m_E[trim.m_ei];
05055 const ON_Interval edge_domain = edge.Domain();
05056 const int i0 = trim.m_bRev3d ? pline_count-1 : 0;
05057 const int i1 = trim.m_bRev3d ? 0 : pline_count-1;
05058 const int di = trim.m_bRev3d ? -1 : 1;
05059 if ( !(trim.m_pline[i0].e == edge_domain[0]) )
05060 {
05061 if (text_log )
05062 text_log->Print("ON_Brep.m_T[%d].m_pline[%d].e != start of edge domain.\n",ti,i0);
05063 return ON_BrepIsNotValid();
05064 }
05065 if ( !(trim.m_pline[i1].e == edge_domain[1]) )
05066 {
05067 if (text_log )
05068 text_log->Print("ON_Brep.m_T[%d].m_pline[%d].e != end of edge domain.\n",ti,i1);
05069 return ON_BrepIsNotValid();
05070 }
05071 int prev_valid_i = i0;
05072 for ( int i = i0+di; i >= 0 && i < pline_count && i-di >= 0 && i-di < pline_count; i += di )
05073 {
05074 if ( !ON_IsValid(trim.m_pline[i].e) )
05075 {
05076
05077
05078
05079
05080 continue;
05081 }
05082 if ( !(trim.m_pline[prev_valid_i].e < trim.m_pline[i].e) )
05083 {
05084 if (text_log )
05085 text_log->Print("ON_Brep.m_T[%d].m_pline[%d].t must be < m_pline[%d].t.\n",ti,prev_valid_i,i);
05086 return ON_BrepIsNotValid();
05087 }
05088 prev_valid_i = i;
05089 }
05090 }
05091 #endif
05092
05093 return true;
05094 }
05095
05096
05097
05098 bool ON_Brep::SetEdgeVertex( const int ei, const int evi, const int vi )
05099 {
05100 if ( ei < 0 || vi < 0 || evi < 0 || evi > 1 )
05101 return false;
05102 ON_BrepEdge& edge = m_E[ei];
05103 if ( edge.m_vi[evi] != vi ) {
05104 edge.m_vi[evi] = vi;
05105 ON_BrepVertex& vertex = m_V[vi];
05106 vertex.m_ei.Append(ei);
05107 }
05108 const int trim_count = edge.m_ti.Count();
05109 int eti, ti, tvi;
05110 for ( eti = 0; eti < trim_count; eti++ ) {
05111 ti = edge.m_ti[eti];
05112 if ( ti < 0 )
05113 continue;
05114 ON_BrepTrim& trim = m_T[ti];
05115 tvi = trim.m_bRev3d ? 1-evi : evi;
05116 trim.m_vi[tvi] = vi;
05117 }
05118 return true;
05119 }
05120
05121 bool ON_Brep::HopAcrossEdge( int& ti, int& tvi ) const
05122 {
05123
05124
05125 int ei, evi, new_ti, new_tvi;
05126 if ( ti < 0 )
05127 return false;
05128 ei = m_T[ti].m_ei;
05129 if ( ei < 0 )
05130 return false;
05131 const ON_BrepEdge& edge = m_E[ei];
05132 if ( edge.m_ti.Count() < 2 )
05133 return false;
05134 evi = (m_T[ti].m_bRev3d) ? 1-tvi : tvi;
05135 new_ti = edge.m_ti[(edge.m_ti[0] == ti)?1:0];
05136 if ( new_ti < 0 )
05137 return false;
05138 new_tvi = (m_T[new_ti].m_bRev3d) ? 1-evi : evi;
05139 ti = new_ti;
05140 tvi = new_tvi;
05141 return true;
05142 }
05143
05144 bool ON_Brep::SetTrimStartVertex( const int ti0, const int vi )
05145 {
05146
05147
05148 if ( ti0 < 0 || vi < 0 )
05149 return false;
05150 int next_ti, ti, ei, evi, tvi, counter;
05151
05152
05153
05154 for ( ti = ti0, tvi = 0, counter = 0; ti >= 0 && counter < 512; counter++ ) {
05155 if ( counter > 0 ) {
05156 if ( ti == ti0 && tvi == 0 )
05157 return true;
05158 }
05159 ON_BrepTrim& trim = m_T[ti];
05160 if ( trim.m_type == ON_BrepTrim::singular ) {
05161 trim.m_vi[0] = trim.m_vi[1] = vi;
05162 tvi = 1-tvi;
05163 next_ti = (tvi) ? NextTrim(ti) : PrevTrim(ti);
05164 ti = next_ti;
05165 tvi = 1-tvi;
05166 if ( ti == ti0 && tvi == 0 )
05167 return true;
05168 if ( m_T[ti].m_type != ON_BrepTrim::singular )
05169 HopAcrossEdge( ti, tvi );
05170 continue;
05171 }
05172
05173 ei = trim.m_ei;
05174 evi = (trim.m_bRev3d) ? 1-tvi : tvi;
05175 if ( !SetEdgeVertex( ei, evi, vi ) )
05176 return false;
05177 next_ti = (tvi) ? NextTrim(ti) : PrevTrim(ti);
05178 ti = next_ti;
05179 tvi = 1-tvi;
05180 if ( ti < 0 )
05181 return false;
05182
05183 if ( m_T[ti].m_type == ON_BrepTrim::singular )
05184 continue;
05185 ei = m_T[ti].m_ei;
05186 if ( ei < 0 )
05187 return false;
05188 evi = (m_T[ti].m_bRev3d) ? 1-tvi : tvi;
05189 const int edge_trim_count = m_E[ei].m_ti.Count();
05190 if ( edge_trim_count < 1 )
05191 break;
05192 if ( edge_trim_count == 1 ) {
05193 SetEdgeVertex( ei, evi, vi );
05194 break;
05195 }
05196 if ( !HopAcrossEdge( ti, tvi ) )
05197 return false;
05198 }
05199
05200
05201
05202
05203 ti = ti0;
05204 tvi = 0;
05205 if ( m_T[ti].m_type == ON_BrepTrim::singular ) {
05206
05207 while ( m_T[ti].m_type == ON_BrepTrim::singular ) {
05208 if ( ti != ti0 ) {
05209 m_T[ti].m_vi[0] = vi;
05210 m_T[ti].m_vi[1] = vi;
05211 }
05212 ti = PrevTrim(ti);
05213 tvi = 1;
05214 if ( ti == ti0 )
05215 break;
05216 }
05217 ei = m_T[ti].m_ei;
05218 if ( ei >= 0 ) {
05219 evi = (m_T[ti].m_bRev3d) ? 1-tvi : tvi;
05220 SetEdgeVertex( ei, evi, vi );
05221 }
05222 }
05223 else {
05224 ei = m_T[ti].m_ei;
05225 }
05226 if ( ei < 0 ) {
05227
05228
05229 return true;
05230 }
05231 if ( m_E[ei].m_ti.Count() < 2 )
05232 return true;
05233 if ( !HopAcrossEdge( ti, tvi ) )
05234 return false;
05235 next_ti = (tvi) ? NextTrim(ti) : PrevTrim(ti);
05236 if ( next_ti < 0 )
05237 return false;
05238 ti = next_ti;
05239 tvi = 1-tvi;
05240 if ( m_T[ti].m_type != ON_BrepTrim::singular ) {
05241 ei = m_T[ti].m_ei;
05242 if ( ei < 0 )
05243 return false;
05244 if ( m_E[ei].m_ti.Count() == 1 ) {
05245 evi = (m_T[ti].m_bRev3d)? 1-tvi : tvi;
05246 SetEdgeVertex( ei, evi, vi );
05247 return true;
05248 }
05249 if ( !HopAcrossEdge( ti, tvi ) )
05250 return false;
05251 }
05252
05253 const int ti1 = ti;
05254 const int tvi1 = tvi;
05255
05256 for ( ti = ti1, tvi = tvi1, counter = 0; ti >= 0 && counter < 512; counter++ ) {
05257 if ( counter > 0 ) {
05258 if ( ti == ti1 && tvi == tvi1 )
05259 return false;
05260 }
05261 ON_BrepTrim& trim = m_T[ti];
05262 if ( trim.m_type == ON_BrepTrim::singular ) {
05263 trim.m_vi[0] = trim.m_vi[1] = vi;
05264 tvi = 1-tvi;
05265 next_ti = (tvi) ? NextTrim(ti) : PrevTrim(ti);
05266 ti = next_ti;
05267 tvi = 1-tvi;
05268 if ( ti == ti1 && tvi == tvi1 )
05269 return false;
05270 if ( m_T[ti].m_type != ON_BrepTrim::singular )
05271 HopAcrossEdge( ti, tvi );
05272 continue;
05273 }
05274
05275 ei = trim.m_ei;
05276 evi = (trim.m_bRev3d) ? 1-tvi : tvi;
05277 if ( !SetEdgeVertex( ei, evi, vi ) )
05278 return false;
05279 next_ti = (tvi) ? NextTrim(ti) : PrevTrim(ti);
05280 ti = next_ti;
05281 tvi = 1-tvi;
05282 if ( ti < 0 )
05283 return false;
05284
05285 if ( m_T[ti].m_type == ON_BrepTrim::singular )
05286 continue;
05287 ei = m_T[ti].m_ei;
05288 if ( ei < 0 )
05289 return false;
05290 evi = (m_T[ti].m_bRev3d) ? 1-tvi : tvi;
05291 const int edge_trim_count = m_E[ei].m_ti.Count();
05292 if ( edge_trim_count < 1 )
05293 break;
05294 if ( edge_trim_count == 1 ) {
05295 SetEdgeVertex( ei, evi, vi );
05296 return true;
05297 }
05298 if ( !HopAcrossEdge( ti, tvi ) )
05299 return false;
05300 }
05301
05302 return false;
05303 }
05304
05305 void ON_Brep::SetLoopVertices( const int li )
05306 {
05307 ON_BrepLoop& loop = m_L[li];
05308 const int loop_trim_count = loop.m_ti.Count();
05309 int lti;
05310 for ( lti = 0; lti < loop_trim_count; lti++ ) {
05311 const int ti = loop.m_ti[lti];
05312 ON_BrepTrim& trim = m_T[ti];
05313 int vi = trim.m_vi[0];
05314 if ( vi >= 0 )
05315 continue;
05316 ON_BrepVertex& v = NewVertex();
05317 SetTrimStartVertex( ti, v.m_vertex_index );
05318 }
05319 }
05320
05321 void ON_Brep::ClearTrimVertices()
05322 {
05323 int ti;
05324 const int tcnt = m_T.Count();
05325 for ( ti = 0; ti < tcnt; ti++ ) {
05326 ON_BrepTrim& trim = m_T[ti];
05327 trim.m_vi[0] = -1;
05328 trim.m_vi[1] = -1;
05329 }
05330 }
05331
05332 void ON_Brep::ClearEdgeVertices()
05333 {
05334 int ei;
05335 const int ecnt = m_E.Count();
05336 for ( ei = 0; ei < ecnt; ei++ ) {
05337 ON_BrepEdge& edge = m_E[ei];
05338 edge.m_vi[0] = -1;
05339 edge.m_vi[1] = -1;
05340 }
05341 }
05342
05343 int ON_Brep::NextTrim(int ti) const
05344 {
05345 const ON_BrepTrim& trim = m_T[ti];
05346 const int li = trim.m_li;
05347 const ON_BrepLoop& loop = m_L[li];
05348 const int trim_count = loop.m_ti.Count();
05349 int lti;
05350 for ( lti = 0; lti < trim_count && loop.m_ti[lti] != ti; lti++)
05351 ;
05352 if ( lti < 0 || lti >= trim_count )
05353 return -1;
05354 return loop.m_ti[(lti+1)%trim_count];
05355 }
05356
05357 int ON_Brep::PrevTrim(int ti) const
05358 {
05359 const ON_BrepTrim& trim = m_T[ti];
05360 const int li = trim.m_li;
05361 const ON_BrepLoop& loop = m_L[li];
05362 const int trim_count = loop.m_ti.Count();
05363 int lti;
05364 for ( lti = 0; loop.m_ti[lti] != ti && lti < trim_count; lti++)
05365 ;
05366 if ( lti < 0 || lti >= trim_count )
05367 return -1;
05368 return loop.m_ti[(lti+trim_count-1)%trim_count];
05369 }
05370
05371 int ON_Brep::NextEdge(int ei, int endi, int* next_endi ) const
05372 {
05373 const ON_BrepEdge& edge = m_E[ei];
05374 const int vi = edge.m_vi[endi];
05375 const ON_BrepVertex& vertex = m_V[vi];
05376 const int edge_count = vertex.m_ei.Count();
05377 int vei;
05378 if ( edge_count < 2 )
05379 return -1;
05380 if ( next_endi )
05381 *next_endi = 0;
05382 for ( vei = 0; vertex.m_ei[vei] != ei && vei < edge_count; vei++)
05383 ;
05384 if ( edge.m_vi[0] == edge.m_vi[1] && endi ) {
05385
05386
05387
05388
05389
05390
05391 vei++;
05392 while ( vei < edge_count && vertex.m_ei[vei] != ei )
05393 vei++;
05394 }
05395 if ( vei < 0 || vei >= edge_count )
05396 return -1;
05397 vei = (vei+1)%edge_count;
05398 const int next_ei = vertex.m_ei[vei];
05399 if ( next_endi ) {
05400 if ( m_E[next_ei].m_vi[0] == m_E[next_ei].m_vi[1] ) {
05401 *next_endi = 1;
05402 for ( vei++; vei < edge_count; vei++ ) {
05403 if ( vertex.m_ei[vei] == next_ei ) {
05404 *next_endi = 0;
05405 break;
05406 }
05407 }
05408 }
05409 else if ( m_E[next_ei].m_vi[1] == vi )
05410 *next_endi = 1;
05411 }
05412 return next_ei;
05413 }
05414
05415 int ON_Brep::PrevEdge(int ei, int endi, int* prev_endi ) const
05416 {
05417 const ON_BrepEdge& edge = m_E[ei];
05418 const int vi = edge.m_vi[endi];
05419 const ON_BrepVertex& vertex = m_V[vi];
05420 const int edge_count = vertex.m_ei.Count();
05421 if ( edge_count < 2 )
05422 return -1;
05423 int vei;
05424 if ( prev_endi )
05425 *prev_endi = 0;
05426 for ( vei = 0; vertex.m_ei[vei] != ei && vei < edge_count; vei++)
05427 ;
05428 if ( edge.m_vi[0] == edge.m_vi[1] && endi ) {
05429
05430
05431
05432
05433
05434
05435 vei++;
05436 while ( vei < edge_count && vertex.m_ei[vei] != ei )
05437 vei++;
05438 }
05439 if ( vei < 0 || vei >= edge_count )
05440 return -1;
05441 vei = (vei+edge_count-1)%edge_count;
05442 const int prev_ei = vertex.m_ei[(vei+edge_count-1)%edge_count];
05443 if ( prev_endi ) {
05444 if ( m_E[prev_ei].m_vi[0] == m_E[prev_ei].m_vi[1] ) {
05445 *prev_endi = 1;
05446 for ( vei++; vei < edge_count; vei++ ) {
05447 if ( vertex.m_ei[vei] == prev_ei ) {
05448 *prev_endi = 0;
05449 break;
05450 }
05451 }
05452 }
05453 else if ( m_E[prev_ei].m_vi[1] == vi ) {
05454 *prev_endi = 1;
05455 }
05456 }
05457 return prev_ei;
05458 }
05459
05460
05461 class ON__EDGE_ENDS
05462 {
05463 public:
05464
05465
05466 int vi0;
05467 int vi1;
05468 int ei;
05469 bool operator<(const ON__EDGE_ENDS& other) const
05470 {
05471 int i = other.vi0 - vi0;
05472 if ( i < 0 ) return true;
05473 if ( i > 0 ) return false;
05474 i = other.vi1 - vi1;
05475 if ( i < 0 ) return true;
05476 if ( i > 0 ) return false;
05477 i = other.ei - ei;
05478 if ( i < 0 ) return true;
05479 return false;
05480 }
05481 };
05482
05483 void ON_Brep::SetVertices(void)
05484 {
05485 const int face_count = m_F.Count();
05486 int fi;
05487
05488 ClearEdgeVertices();
05489 ClearTrimVertices();
05490 m_V.Empty();
05491 m_V.Shrink();
05492 fi = m_E.Count() - m_F.Count() + 8;
05493 if ( fi < 32 )
05494 fi = 32;
05495 m_V.Reserve( fi );
05496 for ( fi = 0; fi < face_count; fi++ ) {
05497 ON_BrepFace& face = m_F[fi];
05498 const int loop_count = face.m_li.Count();
05499 int fli;
05500 for ( fli = 0; fli < loop_count; fli++ ) {
05501 SetLoopVertices( face.m_li[fli] );
05502 }
05503 }
05504
05505
05506 const int vertex_count = m_V.Count();
05507 int vi;
05508 ON_3dPoint VP, EP;
05509 for ( vi = 0; vi < vertex_count; vi++ )
05510 {
05511 VP.Zero();
05512 double d = 0.0;
05513 ON_BrepVertex& vertex = m_V[vi];
05514 const int edge_count = vertex.m_ei.Count();
05515 int vei;
05516 for ( vei = 0; vei < edge_count; vei++ )
05517 {
05518 const int ei = vertex.m_ei[vei];
05519 if ( ei < 0 )
05520 continue;
05521 const ON_BrepEdge& edge = m_E[ei];
05522 if ( edge.m_c3i < 0 )
05523 continue;
05524 const ON_Curve* pC = edge.EdgeCurveOf();
05525 if ( !pC )
05526 continue;
05527 if ( edge.m_vi[0] == vi )
05528 EP = edge.PointAtStart();
05529 else if ( edge.m_vi[1] == vi )
05530 EP = edge.PointAtEnd();
05531 else
05532 continue;
05533 VP.x += EP.x;
05534 VP.y += EP.y;
05535 VP.z += EP.z;
05536 d += 1.0;
05537 }
05538 if ( d > 0.0 )
05539 {
05540 d = 1.0/d;
05541 vertex.point = d*VP;
05542 }
05543 }
05544
05545 const int edge_count = m_E.Count();
05546 int ei;
05547 ON_SimpleArray<ON__EDGE_ENDS> edge_ends(edge_count/4 + 2);
05548 for ( ei = 0; ei < edge_count; ei++ )
05549 {
05550
05551
05552 const ON_BrepEdge& edge = m_E[ei];
05553 if ( edge.m_vi[0] >= 0
05554 && edge.m_vi[1] >= 0
05555 && edge.m_vi[0] != edge.m_vi[1]
05556 && 0 != edge.EdgeCurveOf()
05557 && edge.IsClosed() )
05558 {
05559 ON__EDGE_ENDS& ee = edge_ends.AppendNew();
05560 if ( edge.m_vi[0] < edge.m_vi[1] )
05561 {
05562 ee.vi0 = edge.m_vi[0];
05563 ee.vi1 = edge.m_vi[1];
05564 }
05565 else
05566 {
05567 ee.vi0 = edge.m_vi[1];
05568 ee.vi1 = edge.m_vi[0];
05569 }
05570 ee.ei = ei;
05571 }
05572 }
05573
05574 if ( edge_ends.Count() > 0 )
05575 {
05576
05577 edge_ends.QuickSort( ON_CompareIncreasing<ON__EDGE_ENDS> );
05578 int edge_ends_count = edge_ends.Count();
05579 int i0, i1, vi0, vi1, i;
05580
05581
05582 for ( i = 1; i < edge_ends_count; i++ )
05583 {
05584 bool bSortAgain = false;
05585 for ( i0 = 0; i0 < edge_ends_count; i0++ )
05586 {
05587 vi0 = edge_ends[i0].vi0;
05588 vi1 = edge_ends[i0].vi1;
05589 for ( i1 = i0+1; i1 < edge_ends_count; i1++ )
05590 {
05591 ON__EDGE_ENDS& ee = edge_ends[i1];
05592 if ( ee.vi0 == vi1 )
05593 {
05594 ee.vi0 = vi0;
05595 bSortAgain = true;
05596 }
05597 if ( ee.vi1 == vi1 )
05598 {
05599 ee.vi1 = ee.vi0;
05600 ee.vi0 = vi0;
05601 bSortAgain = true;
05602 }
05603 }
05604 }
05605 if ( bSortAgain )
05606 {
05607 edge_ends.QuickSort( ON_CompareIncreasing<ON__EDGE_ENDS> );
05608 }
05609 else
05610 break;
05611 }
05612
05613
05614 bool bCullUnusedVertices = false;
05615 for ( i0 = 0, i1 = 1; i0 < edge_ends.Count(); i0 = i1 )
05616 {
05617 vi0 = edge_ends[i0].vi0;
05618 for ( i1 = i0+1; i1 < edge_ends.Count() && vi0 == edge_ends[i1].vi0; i1++ )
05619 {
05620
05621 }
05622 vi1 = vi0;
05623 for ( i = i0; i < i1; i++ )
05624 {
05625 if ( edge_ends[i].vi1 > vi1 )
05626 {
05627 vi1 = edge_ends[i].vi1;
05628 if ( 0 <= vi0 && vi0 < vi1 && vi1 < m_V.Count())
05629 {
05630 CombineCoincidentVertices(m_V[vi0],m_V[vi1] );
05631 bCullUnusedVertices = true;
05632 }
05633 }
05634 }
05635 }
05636 if ( bCullUnusedVertices )
05637 CullUnusedVertices();
05638 }
05639 }
05640
05641 void ON_BrepTrim::m__legacy_flags_Set(int gcon, int mono)
05642 {
05643 m__legacy_flags = 0;
05644 switch(gcon)
05645 {
05646 case -1:
05647 m__legacy_flags |= 1;
05648 break;
05649 case 0:
05650 m__legacy_flags |= 2;
05651 break;
05652 case 1:
05653 m__legacy_flags |= 3;
05654 break;
05655 case 2:
05656 m__legacy_flags |= 4;
05657 break;
05658 }
05659 if (mono)
05660 m__legacy_flags |= 8;
05661 else
05662 m__legacy_flags |= 16;
05663 }
05664
05665 bool ON_BrepTrim::m__legacy_flags_Get(int* gcon, int* mono) const
05666 {
05667 if ( gcon ) {
05668 switch ( m__legacy_flags & 7 )
05669 {
05670 case 1:
05671 *gcon = -1;
05672 break;
05673 case 2:
05674 *gcon = 0;
05675 break;
05676 case 3:
05677 *gcon = 1;
05678 break;
05679 case 4:
05680 *gcon = 2;
05681 break;
05682 default:
05683 *gcon = -1;
05684 }
05685 }
05686 if ( mono ) {
05687 if ( 0 != (m__legacy_flags&8) )
05688 *mono = 1;
05689 else
05690 *mono = 0;
05691 }
05692 return m__legacy_flags ? true : false;
05693 }
05694 void ON_Brep::SetTolsFromLegacyValues()
05695 {
05696
05697 const int vcnt = m_V.Count();
05698 const int tcnt = m_T.Count();
05699 ON_3dPoint endP;
05700 double d;
05701 int vi, ti, vei, evi, vecnt;
05702
05703
05704 for ( ti = 0; ti < tcnt; ti++ ) {
05705 ON_BrepTrim& trim = m_T[ti];
05706 trim.m_tolerance[0] = trim.m__legacy_2d_tol;
05707 trim.m_tolerance[1] = trim.m__legacy_2d_tol;
05708 if ( trim.m_ei >= 0 ) {
05709 ON_BrepEdge& edge = m_E[trim.m_ei];
05710 if ( edge.m_tolerance < trim.m__legacy_3d_tol )
05711 edge.m_tolerance = trim.m__legacy_3d_tol;
05712 }
05713 }
05714
05715
05716 for ( vi = 0; vi < vcnt; vi++ ) {
05717 ON_BrepVertex& vertex = m_V[vi];
05718 vecnt = vertex.m_ei.Count();
05719 for ( vei = 0; vei < vecnt; vei++ ) {
05720 const ON_BrepEdge& edge = m_E[vertex.m_ei[vei]];
05721 if ( vertex.m_tolerance < edge.m_tolerance )
05722 vertex.m_tolerance = edge.m_tolerance;
05723 const ON_Curve* c = m_C3[edge.m_c3i];
05724 evi = 0;
05725 if ( edge.m_vi[0] != vi )
05726 evi = 1;
05727 if ( edge.m_vi[evi] == vi ) {
05728 endP = c->PointAt( c->Domain()[evi] );
05729 d = vertex.point.DistanceTo( endP );
05730 if ( d > vertex.m_tolerance ) {
05731 vertex.m_tolerance = d;
05732 }
05733 }
05734 }
05735 }
05736 }
05737
05738 ON::object_type ON_Brep::ObjectType() const
05739 {
05740
05741
05742
05743 return ON::brep_object;
05744 }
05745
05746 void ON_Brep::ClearBoundingBox()
05747 {
05748 m_bbox.Destroy();
05749 }
05750
05751 void ON_BrepFace::ClearBoundingBox()
05752 {
05753 m_bbox.Destroy();
05754 }
05755
05756 ON_BOOL32
05757 ON_BrepFace::GetBBox(
05758 double* box_min,
05759 double* box_max,
05760 ON_BOOL32 bGrowBox
05761 ) const
05762 {
05763 if ( !m_bbox.IsValid()
05764 && 0 != m_brep
05765 && m_face_index >= 0
05766 && m_face_index < m_brep->m_F.Count()
05767 && &m_brep->m_F[m_face_index] == this
05768 )
05769 {
05770 const ON_Surface* srf = ProxySurface();
05771 if ( srf && srf != this )
05772 {
05773 srf->GetBoundingBox( const_cast<ON_BrepFace*>(this)->m_bbox, false );
05774 }
05775 }
05776
05777 ON_BOOL32 rc = m_bbox.IsValid();
05778 if (rc)
05779 {
05780 ON_BoundingBox bbox = m_bbox;
05781 if ( bGrowBox && box_min && box_max && box_min[0] <= box_max[0] )
05782 {
05783 bbox.Union( ON_BoundingBox( ON_3dPoint(box_min), ON_3dPoint(box_max) ) );
05784 }
05785 if ( box_min )
05786 {
05787 box_min[0] = bbox.m_min.x;
05788 box_min[1] = bbox.m_min.y;
05789 box_min[2] = bbox.m_min.z;
05790 }
05791 if ( box_max )
05792 {
05793 box_max[0] = bbox.m_max.x;
05794 box_max[1] = bbox.m_max.y;
05795 box_max[2] = bbox.m_max.z;
05796 }
05797 }
05798 return rc;
05799 }
05800
05801
05802 ON_BOOL32
05803 ON_Brep::GetBBox(
05804 double* box_min,
05805 double* box_max,
05806 ON_BOOL32 bGrowBox
05807 ) const
05808 {
05809 ON_BoundingBox bbox;
05810 if ( !m_bbox.IsValid() )
05811 {
05812 const int face_count = m_F.Count();
05813 int fi;
05814 for ( fi = 0; fi < face_count; fi++ )
05815 {
05816 if ( m_F[fi].m_face_index == -1 )
05817 continue;
05818 const ON_Surface* srf = m_F[fi].ProxySurface();
05819 if ( !srf )
05820 continue;
05821 srf->GetBoundingBox( bbox, bbox.IsValid() );
05822 }
05823 ON_Brep* ptr = const_cast<ON_Brep*>(this);
05824 ptr->m_bbox = bbox;
05825 }
05826
05827 ON_BOOL32 rc = m_bbox.IsValid();
05828 if (rc)
05829 {
05830 bbox = m_bbox;
05831 if ( bGrowBox && box_min && box_max && box_min[0] <= box_max[0] )
05832 {
05833 bbox.Union( ON_BoundingBox( ON_3dPoint(box_min), ON_3dPoint(box_max) ) );
05834 }
05835 if ( box_min )
05836 {
05837 box_min[0] = bbox.m_min.x;
05838 box_min[1] = bbox.m_min.y;
05839 box_min[2] = bbox.m_min.z;
05840 }
05841 if ( box_max )
05842 {
05843 box_max[0] = bbox.m_max.x;
05844 box_max[1] = bbox.m_max.y;
05845 box_max[2] = bbox.m_max.z;
05846 }
05847 }
05848 return rc;
05849 }
05850
05851 ON_BOOL32
05852 ON_Brep::SwapCoordinates( int i, int j )
05853 {
05854 ON_BOOL32 rc = false;
05855
05856 const int srf_count = m_S.Count();
05857 int si;
05858 for ( si = 0; si < srf_count; si++ ) {
05859 if ( !m_S[si] )
05860 continue;
05861 rc = m_S[si]->SwapCoordinates(i,j);
05862 if ( !rc ) {
05863 while ( --si >= 0 ) {
05864
05865 if ( m_S[si] )
05866 m_S[si]->SwapCoordinates(i,j);
05867 }
05868 return false;
05869 }
05870 }
05871
05872 const int crv_count = m_S.Count();
05873 int ci;
05874 for ( ci = 0; ci < crv_count; ci++ ) {
05875 if ( !m_C3[ci] )
05876 continue;
05877 rc = m_C3[ci]->SwapCoordinates(i,j);
05878 if ( !rc ) {
05879
05880 while ( --ci >= 0 ) {
05881 if ( m_C3[ci] )
05882 m_C3[ci]->SwapCoordinates(i,j);
05883 for ( si = 0; si < srf_count; si++ ) {
05884 if ( m_S[si] )
05885 m_S[si]->SwapCoordinates(i,j);
05886 }
05887 }
05888 return false;
05889 }
05890 }
05891 return rc;
05892 }
05893
05894 bool
05895 ON_Brep::SwapTrimParameters(
05896 int trim_index
05897 )
05898 {
05899
05900 if ( trim_index < 0 || trim_index >= m_T.Count() )
05901 return false;
05902 ON_BrepTrim& trim = m_T[trim_index];
05903
05904 StandardizeTrimCurve(trim_index);
05905
05906 const int ci = trim.m_c2i;
05907 if ( ci < 0 || ci >= m_C2.Count() )
05908 return false;
05909 ON_Curve* pC = m_C2[ci];
05910 if ( !pC )
05911 return false;
05912
05913 ON_Interval pdom = trim.ProxyCurveDomain();
05914 ON_Interval trimdom = trim.Domain();
05915
05916
05917
05918
05919 ON_BOOL32 rc = pC->SwapCoordinates(0,1);
05920 if ( !rc )
05921 return false;
05922
05923
05924 rc = pC->Reverse();
05925 if (rc)
05926 {
05927
05928 trim.SetProxyCurve(pC);
05929 int i = trim.m_vi[0];
05930 trim.m_vi[0] = trim.m_vi[1];
05931 trim.m_vi[1] = i;
05932 if ( trim.m_ei >= 0 )
05933 trim.m_bRev3d = trim.m_bRev3d ? false : true;
05934 }
05935 else
05936 {
05937
05938 rc = pC->SwapCoordinates(0,1);
05939 return false;
05940 }
05941
05942
05943 switch ( trim.m_iso )
05944 {
05945 case ON_Surface::not_iso:
05946 trim.m_iso = ON_Surface::not_iso;
05947 break;
05948 case ON_Surface::x_iso:
05949 trim.m_iso = ON_Surface::y_iso;
05950 break;
05951 case ON_Surface::y_iso:
05952 trim.m_iso = ON_Surface::x_iso;
05953 break;
05954 case ON_Surface::W_iso:
05955 trim.m_iso = ON_Surface::S_iso;
05956 break;
05957 case ON_Surface::S_iso:
05958 trim.m_iso = ON_Surface::W_iso;
05959 break;
05960 case ON_Surface::E_iso:
05961 trim.m_iso = ON_Surface::N_iso;
05962 break;
05963 case ON_Surface::N_iso:
05964 trim.m_iso = ON_Surface::E_iso;
05965 break;
05966 default:
05967 trim.m_iso = ON_Surface::not_iso;
05968 break;
05969 }
05970
05971 return true;
05972 }
05973
05974 bool
05975 ON_Brep::SwapLoopParameters(
05976 int loop_index
05977 )
05978 {
05979 bool rc = false;
05980 if ( loop_index < 0 || loop_index >= m_L.Count() )
05981 return false;
05982 ON_BrepLoop& L = m_L[loop_index];
05983 const int loop_trim_count = L.m_ti.Count();
05984 if ( loop_trim_count < 1 )
05985 return false;
05986 int lti, ti;
05987 for ( lti = 0; lti < loop_trim_count; lti++ ) {
05988 ti = L.m_ti[lti];
05989 rc = SwapTrimParameters( ti );
05990 if ( !rc ) {
05991 while ( --lti >= 0 ) {
05992
05993 ti = L.m_ti[lti];
05994 SwapTrimParameters( ti );
05995 }
05996 return false;
05997 }
05998 }
05999
06000
06001 if ( rc )
06002 L.m_ti.Reverse();
06003 return rc;
06004 }
06005
06006 bool
06007 ON_Brep::IsSolid() const
06008 {
06009 ON_BOOL32 bIsOriented = false;
06010 ON_BOOL32 bHasBoundary = true;
06011 bool bIsManifold = IsManifold( &bIsOriented, &bHasBoundary );
06012 return (bIsManifold && bIsOriented && !bHasBoundary) ? true : false;
06013 }
06014
06015 int ON_Brep::SolidOrientation() const
06016 {
06017
06018
06019
06020
06021
06022 int rc = 0;
06023 switch( m_is_solid )
06024 {
06025 case 1:
06026 rc = 1;
06027 break;
06028 case 2:
06029 rc = -1;
06030 break;
06031 case 3:
06032 rc = 0;
06033 break;
06034
06035 default:
06036 if ( IsSolid() )
06037 {
06038
06039
06040
06041
06042
06043
06044
06045 rc = 2;
06046 }
06047 else
06048 {
06049 ON_Brep* p = const_cast<ON_Brep*>(this);
06050 p->m_is_solid = 3;
06051 rc = 0;
06052 }
06053 }
06054 return rc;
06055 }
06056
06057 bool
06058 ON_Brep::IsManifold( ON_BOOL32* pbIsOriented, ON_BOOL32* pbHasBoundary ) const
06059 {
06060 const int fcnt = m_F.Count();
06061 bool bIsManifold = (fcnt > 0) ? true : false;
06062 bool bIsOriented = bIsManifold;
06063 bool bHasBoundary = false;
06064 int fi, other_ti, lcnt, tcnt, fli, lti;
06065 if ( pbIsOriented )
06066 *pbIsOriented = bIsOriented;
06067 if ( pbHasBoundary )
06068 *pbHasBoundary = bHasBoundary;
06069 const int brep_loop_count = m_L.Count();
06070 const int brep_trim_count = m_T.Count();
06071 const int brep_edge_count = m_E.Count();
06072 for ( fi = 0; fi < fcnt && bIsManifold; fi++ )
06073 {
06074 const ON_BrepFace& face = m_F[fi];
06075 if ( -1 == face.m_face_index )
06076 {
06077
06078
06079
06080
06081
06082 continue;
06083 }
06084
06085 lcnt = face.m_li.Count();
06086 if ( lcnt < 1 ) {
06087 bIsManifold = false;
06088 }
06089
06090 for ( fli = 0; fli < lcnt && bIsManifold; fli++ )
06091 {
06092 const int li = face.m_li[fli];
06093 if ( li < 0 || li >= brep_loop_count )
06094 {
06095 ON_ERROR("Bogus loop index in face.m_li[]");
06096 continue;
06097 }
06098 const ON_BrepLoop& loop = m_L[li];
06099 tcnt = loop.m_ti.Count();
06100 if (tcnt < 1 ) {
06101 bIsManifold = false;
06102 }
06103 for ( lti = 0; lti < tcnt && bIsManifold; lti++ )
06104 {
06105 const int ti = loop.m_ti[lti];
06106 if ( ti < 0 || ti >= brep_trim_count )
06107 {
06108 ON_ERROR("Bogus loop index in loop.m_ti[]");
06109 continue;
06110 }
06111 const ON_BrepTrim& trim = m_T[ti];
06112 switch ( trim.m_type )
06113 {
06114 case ON_BrepTrim::boundary:
06115 bHasBoundary = true;
06116 break;
06117 case ON_BrepTrim::mated:
06118 case ON_BrepTrim::seam:
06119
06120 if ( trim.m_ei >= 0 && trim.m_ei < brep_edge_count )
06121 {
06122 const ON_BrepEdge& edge = m_E[trim.m_ei];
06123 if ( edge.m_ti.Count() != 2 ) {
06124 bIsManifold = false;
06125 }
06126 else
06127 {
06128 other_ti = edge.m_ti[0];
06129 if ( other_ti == ti )
06130 other_ti = edge.m_ti[1];
06131 if ( other_ti == ti )
06132 {
06133 bIsManifold = false;
06134 }
06135 else
06136 {
06137 const ON_BrepTrim& other_trim = m_T[other_ti];
06138
06139
06140
06141
06142 ON_BOOL32 bFlipTrim = trim.m_bRev3d;
06143 if (0 <= trim.m_li && brep_loop_count > trim.m_li)
06144 {
06145 if ( m_F[m_L[trim.m_li].m_fi].m_bRev )
06146 bFlipTrim = !bFlipTrim;
06147 }
06148 else
06149 {
06150 ON_ERROR("Bogus loop index in trim.m_li");
06151 continue;
06152 }
06153
06154 ON_BOOL32 bFlipOther = other_trim.m_bRev3d;
06155 if (0 <= other_trim.m_li && brep_loop_count > other_trim.m_li)
06156 {
06157 if ( m_F[m_L[other_trim.m_li].m_fi].m_bRev )
06158 bFlipOther = !bFlipOther;
06159 }
06160 else
06161 {
06162 ON_ERROR("Bogus loop index in other_trim.m_li");
06163 continue;
06164 }
06165
06166 if ( bFlipTrim && bFlipOther )
06167 {
06168 bIsOriented = false;
06169 }
06170 else if ( !bFlipTrim && !bFlipOther )
06171 {
06172 bIsOriented = false;
06173 }
06174 }
06175 }
06176 }
06177 else
06178 {
06179 ON_ERROR("Bogus trim.m_ei or trim.m_type value");
06180 }
06181 break;
06182 case ON_BrepTrim::singular:
06183
06184 break;
06185 default:
06186 bIsManifold = false;
06187 break;
06188 }
06189 }
06190 }
06191 }
06192 if ( !bIsManifold ) {
06193 bIsOriented = false;
06194 bHasBoundary = false;
06195 }
06196 if ( pbIsOriented )
06197 *pbIsOriented = bIsOriented;
06198 if ( pbHasBoundary )
06199 *pbHasBoundary = bHasBoundary;
06200 if ( !bIsManifold || bHasBoundary )
06201 {
06202 if ( m_is_solid != 3 )
06203 {
06204
06205 const_cast<ON_Brep*>(this)->m_is_solid = 3;
06206 }
06207 }
06208
06209 return bIsManifold;
06210 }
06211
06212
06213 bool
06214 ON_Brep::IsSurface() const
06215 {
06216
06217
06218
06219
06220
06221 return (m_F.Count() == 1 && FaceIsSurface(0));
06222 }
06223
06224 bool
06225 ON_Brep::FaceIsSurface( int face_index ) const
06226 {
06227
06228
06229
06230
06231
06232
06233 bool bTrivialFace = false;
06234 if ( face_index >= 0 && face_index < m_F.Count() ) {
06235 const ON_BrepFace& face = m_F[face_index];
06236 if ( face.m_li.Count() == 1 ) {
06237 bTrivialFace = LoopIsSurfaceBoundary( face.m_li[0] );
06238 }
06239 }
06240 return bTrivialFace;
06241 }
06242
06243 bool
06244 ON_Brep::LoopIsSurfaceBoundary( int loop_index ) const
06245 {
06246
06247 bool bTrivialLoop = false;
06248 if ( loop_index >= 0 && loop_index < m_L.Count() ) {
06249 const ON_BrepLoop& loop = m_L[loop_index];
06250 const int trim_count = loop.m_ti.Count();
06251 if ( trim_count > 0 ) {
06252 bTrivialLoop = true;
06253 for ( int lti = 0; lti < trim_count && bTrivialLoop; lti++ )
06254 {
06255 int ti = loop.m_ti[lti];
06256 if ( ti < 0 || ti >= m_T.Count() )
06257 {
06258 ON_ERROR("Bogus trim index in loop.m_ti[]");
06259 return false;
06260 }
06261 const ON_BrepTrim& trim = m_T[ti];
06262 if ( trim.m_iso == ON_Surface::W_iso )
06263 continue;
06264 if ( trim.m_iso == ON_Surface::S_iso )
06265 continue;
06266 if ( trim.m_iso == ON_Surface::N_iso )
06267 continue;
06268 if ( trim.m_iso == ON_Surface::E_iso )
06269 continue;
06270 bTrivialLoop = false;
06271 }
06272 }
06273 }
06274 return bTrivialLoop;
06275 }
06276
06277 bool
06278 ON_Brep::FlipReversedSurfaces()
06279 {
06280
06281
06282
06283
06284
06285
06286
06287
06288
06289
06290
06291
06292 int saved_is_solid = m_is_solid;
06293
06294 const int face_count = m_F.Count();
06295
06296 bool rc = true;
06297 int fi;
06298 for ( fi = 0; fi < face_count; fi++ )
06299 {
06300 ON_BrepFace& face = m_F[fi];
06301 if ( face.m_bRev )
06302 {
06303 if ( !face.Transpose() )
06304 rc = false;
06305 }
06306 }
06307
06308 m_is_solid = saved_is_solid;
06309
06310 return rc;
06311 }
06312
06314
06315 bool ON_Brep::SetTrimDomain(
06316 int trim_index,
06317 const ON_Interval& domain
06318 )
06319 {
06320 bool rc = false;
06321 if ( trim_index >= 0 && trim_index < m_T.Count() && domain.IsIncreasing() )
06322 {
06323 ON_BrepTrim& trim = m_T[trim_index];
06324 rc = trim.SetDomain(domain);
06325 }
06326 return rc;
06327 }
06328
06330
06331 bool ON_Brep::SetEdgeDomain(
06332 int edge_index,
06333 const ON_Interval& domain
06334 )
06335 {
06336 bool rc = false;
06337 if ( edge_index >= 0 && edge_index < m_E.Count() && domain.IsIncreasing() )
06338 {
06339 ON_BrepEdge& edge = m_E[edge_index];
06340 rc = edge.SetDomain(domain);
06341 }
06342 return rc;
06343 }
06344
06345 ON_BOOL32 ON_BrepFace::Reverse(int dir)
06346 {
06347 if ( dir < 0 || dir > 1 || 0 == m_brep )
06348 return false;
06349 ON_Surface* srf = const_cast<ON_Surface*>(SurfaceOf());
06350 if ( !srf )
06351 return false;
06352 ON_Interval dom0 = srf->Domain(dir);
06353 if ( !dom0.IsIncreasing() )
06354 return false;
06355
06356
06357 DestroyRuntimeCache(true);
06358
06359 if ( m_brep->SurfaceUseCount( m_si, 2 ) > 1 )
06360 {
06361 srf = srf->DuplicateSurface();
06362 m_si = m_brep->AddSurface( srf );
06363 SetProxySurface(srf);
06364 }
06365
06366 if ( !srf->Reverse(dir) )
06367 return false;
06368
06369 ON_Interval dom1 = dom0;
06370 dom1.Reverse();
06371 if ( dom1 != srf->Domain(dir) )
06372 {
06373 srf->SetDomain( dir, dom1 );
06374 dom1 = srf->Domain(dir);
06375 }
06376
06377
06378 ON_Xform xform(1);
06379 xform.IntervalChange(dir,dom0,ON_Interval(dom1[1],dom1[0]));
06380 TransformTrim(xform);
06381
06382
06383 int fli;
06384 for ( fli = 0; fli < m_li.Count(); fli++ )
06385 {
06386 ON_BrepLoop* loop = m_brep->Loop(m_li[fli]);
06387 if ( loop )
06388 m_brep->FlipLoop( *loop );
06389 }
06390
06391 m_bRev = m_bRev ? false : true;
06392
06393 if (m_brep->m_is_solid == 1 || m_brep->m_is_solid == 2) m_brep->m_is_solid = 0;
06394
06395
06396
06397 if(m_render_mesh)
06398 {
06399 m_render_mesh->ReverseSurfaceParameters(dir);
06400 m_render_mesh->ReverseTextureCoordinates(dir);
06401 }
06402 if(m_analysis_mesh)
06403 {
06404 m_analysis_mesh->ReverseSurfaceParameters(dir);
06405 m_analysis_mesh->ReverseTextureCoordinates(dir);
06406 }
06407
06408 return true;
06409 }
06410
06411 ON_BOOL32 ON_BrepFace::Transpose()
06412 {
06413 if ( 0 == m_brep )
06414 return false;
06415
06416 ON_Surface* srf = const_cast<ON_Surface*>(SurfaceOf());
06417 if ( 0 == srf )
06418 return false;
06419
06420
06421 DestroyRuntimeCache(true);
06422
06423
06424 if ( m_brep->SurfaceUseCount( m_si, 2 ) > 1 )
06425 {
06426 srf = srf->DuplicateSurface();
06427 m_si = m_brep->AddSurface(srf);
06428 SetProxySurface(srf);
06429 }
06430
06431 ON_Interval u0 = srf->Domain(0);
06432 ON_Interval v0 = srf->Domain(1);
06433
06434
06435 ON_BOOL32 rc = srf->Transpose();
06436 if ( !rc )
06437 return false;
06438
06439 ON_Interval u1 = srf->Domain(0);
06440 ON_Interval v1 = srf->Domain(1);
06441
06442 ON_Xform xform(1);
06443 xform[0][0] = 0.0;
06444 xform[0][1] = 1.0;
06445 xform[1][0] = 1.0;
06446 xform[1][1] = 0.0;
06447
06448 TransformTrim(xform);
06449
06450
06451 int fli;
06452 for ( fli = 0; fli < m_li.Count(); fli++ )
06453 {
06454 ON_BrepLoop* loop = m_brep->Loop(m_li[fli]);
06455 if ( loop )
06456 m_brep->FlipLoop( *loop );
06457 }
06458
06459 m_bRev = m_bRev ? false : true;
06460
06461
06462
06463
06464
06465
06466
06467
06468
06469
06470
06471 if(m_render_mesh)
06472 {
06473 m_render_mesh->TransposeSurfaceParameters();
06474 m_render_mesh->TransposeTextureCoordinates();
06475 }
06476 if(m_analysis_mesh)
06477 {
06478 m_analysis_mesh->TransposeSurfaceParameters();
06479 m_analysis_mesh->TransposeTextureCoordinates();
06480 }
06481
06482 return true;
06483 }
06484
06485 bool ON_BrepFace::SetDomain(
06486 ON_Interval u_dom,
06487 ON_Interval v_dom
06488 )
06489 {
06490 if ( 0 == m_brep )
06491 return false;
06492 if ( !u_dom.IsIncreasing() )
06493 return false;
06494 if ( !v_dom.IsIncreasing() )
06495 return false;
06496
06497 ON_Surface* srf = const_cast<ON_Surface*>(SurfaceOf());
06498 if ( 0 == srf )
06499 return false;
06500
06501 ON_Interval u0_dom = srf->Domain(0);
06502 ON_Interval v0_dom = srf->Domain(1);
06503 if ( u0_dom == u_dom && v0_dom == v_dom )
06504 return true;
06505
06506 ON_Xform xform(1);
06507 {
06508 ON_Xform ux(1), vx(1);
06509 if ( u0_dom != u_dom )
06510 {
06511 if ( !ux.IntervalChange(0,u0_dom,u_dom) )
06512 return false;
06513 }
06514 if ( v0_dom != v_dom )
06515 {
06516 if ( !vx.IntervalChange(1,v0_dom,v_dom) )
06517 return false;
06518 }
06519 xform = ux*vx;
06520 }
06521
06522
06523 DestroyRuntimeCache(true);
06524
06525 if ( m_brep->SurfaceUseCount( m_si, 2 ) > 1 )
06526 {
06527 srf = srf->DuplicateSurface();
06528 m_si = m_brep->AddSurface(srf);
06529 SetProxySurface(srf);
06530 }
06531
06532 if ( u_dom != u0_dom )
06533 {
06534 if ( !srf->SetDomain( 0, u_dom ) )
06535 return false;
06536 }
06537
06538 if ( v_dom != v0_dom )
06539 {
06540 if ( !srf->SetDomain( 1, v_dom ) )
06541 {
06542 srf->SetDomain(0,u0_dom );
06543 return false;
06544 }
06545 }
06546
06547
06548
06549 u_dom = srf->Domain(0);
06550 v_dom = srf->Domain(1);
06551 {
06552 ON_Xform ux(1), vx(1);
06553 if ( u0_dom != u_dom )
06554 {
06555 if ( !ux.IntervalChange(0,u0_dom,u_dom) )
06556 return false;
06557 }
06558 if ( v0_dom != v_dom )
06559 {
06560 if ( !vx.IntervalChange(1,v0_dom,v_dom) )
06561 return false;
06562 }
06563 xform = ux*vx;
06564 }
06565
06566 if ( !TransformTrim(xform) )
06567 return false;
06568
06569 ON_Mesh* mesh[3] = {m_analysis_mesh,m_render_mesh,m_preview_mesh};
06570 for ( int i = 0; i < 3; i++ )
06571 {
06572 if ( 0 == mesh[i] )
06573 continue;
06574 for ( int dir = 0; dir < 2; dir++ )
06575 {
06576 ON_Interval& mdom = mesh[i]->m_srf_domain[dir];
06577 ON_Interval dom0 = dir ? v0_dom : u0_dom;
06578 ON_Interval dom1 = dir ? v_dom : u_dom;
06579 if ( mdom.IsIncreasing() && dom0 != dom1 )
06580 {
06581 if ( mdom == dom0 )
06582 mdom = dom1;
06583 else
06584 {
06585 double t0 = dom1.ParameterAt(dom0.NormalizedParameterAt(mdom[0]));
06586 double t1 = dom1.ParameterAt(dom0.NormalizedParameterAt(mdom[1]));
06587 mdom.Set(t0,t1);
06588 }
06589 }
06590 }
06591 }
06592
06593 return true;
06594 }
06595
06596 ON_BOOL32 ON_BrepFace::SetDomain(
06597 int dir,
06598 double t0,
06599 double t1
06600 )
06601 {
06602 if ( dir < 0
06603 || dir > 1
06604 || t0 == ON_UNSET_VALUE
06605 || t1 == ON_UNSET_VALUE
06606 || t0 >= t1
06607 || 0 == m_brep )
06608 return false;
06609
06610 ON_Surface* srf = const_cast<ON_Surface*>(SurfaceOf());
06611 if ( 0 == srf )
06612 return false;
06613 ON_Interval udom = srf->Domain(0);
06614 ON_Interval vdom = srf->Domain(1);
06615 if ( dir )
06616 vdom.Set(t0,t1);
06617 else
06618 udom.Set(t0,t1);
06619
06620 return SetDomain( udom, vdom );
06621 }
06622
06623
06624
06625
06626
06627
06628
06629
06630
06631
06632
06633
06634
06635
06636
06637
06638 int ON_Brep::TrimCurveUseCount( int c2_index, int max_count ) const
06639 {
06640 int ti, use_count = 0;
06641 if ( max_count < 1 )
06642 max_count = m_T.Count();
06643 for ( ti = 0; ti < m_T.Count() && use_count < max_count; ti++ )
06644 {
06645 if ( m_T[ti].m_c2i == c2_index )
06646 use_count++;
06647 }
06648 return use_count;
06649 }
06650
06651 int ON_Brep::EdgeCurveUseCount( int c3_index, int max_count ) const
06652 {
06653 int ei, use_count = 0;
06654 if ( max_count < 1 )
06655 max_count = m_T.Count();
06656 for ( ei = 0; ei < m_E.Count() && use_count < max_count; ei++ )
06657 {
06658 if ( m_E[ei].m_c3i == c3_index )
06659 use_count++;
06660 }
06661 return use_count;
06662 }
06663
06664 int ON_Brep::SurfaceUseCount( int surface_index, int max_count ) const
06665 {
06666 int fi, use_count = 0;
06667 if ( max_count < 1 )
06668 max_count = m_F.Count();
06669 for ( fi = 0; fi < m_F.Count() && use_count < max_count; fi++ )
06670 {
06671 if ( m_F[fi].m_si == surface_index )
06672 use_count++;
06673 }
06674 return use_count;
06675 }
06676
06678
06679
06680
06681
06682
06683
06684
06685
06686
06687
06688
06689
06690
06691
06692
06693
06694
06695
06696
06697
06698
06699
06700
06701
06702
06703
06704
06705
06706 void
06707 ON_Brep::Flip()
06708 {
06709 const int fcnt = m_F.Count();
06710 int fi;
06711 int missolid = m_is_solid;
06712 for ( fi = 0; fi < fcnt; fi++ ) {
06713 FlipFace(m_F[fi]);
06714 }
06715 if (missolid==1) m_is_solid = 2;
06716 else if (missolid==2) m_is_solid = 1;
06717 }
06718
06719
06720
06721
06722
06723
06724
06725 void
06726 ON_Brep::FlipFace( ON_BrepFace& face )
06727 {
06728 face.m_bRev = (face.m_bRev) ? false : true;
06729 if ( face.m_analysis_mesh )
06730 face.m_analysis_mesh->Flip();
06731 if ( face.m_render_mesh )
06732 face.m_render_mesh->Flip();
06733 if ( face.m_preview_mesh )
06734 face.m_preview_mesh->Flip();
06735
06736
06737
06738 if (0 != m_is_solid)
06739 m_is_solid = 0;
06740 }
06741
06742
06743
06744
06745
06746
06747
06748 void
06749 ON_Brep::FlipLoop(ON_BrepLoop& loop)
06750 {
06751 int ti, lti;
06752 const int brep_trim_count = m_T.Count();
06753 const int loop_trim_count = loop.m_ti.Count();
06754
06755
06756 loop.m_ti.Reverse();
06757
06758 for ( lti = 0; lti < loop_trim_count; lti++ )
06759 {
06760 ti = loop.m_ti[lti];
06761 if ( ti >= 0 && ti < brep_trim_count )
06762 {
06763 m_T[ti].Reverse();
06764 }
06765 }
06766 }
06767
06768 static int curve_area( ON_3dPoint& start_point, const ON_Curve* curve, const ON_Interval& curve_domain, const ON_Xform* xform, double *area )
06769 {
06770
06771
06772
06773 ON_Workspace ws;
06774 ON_Interval span_domain;
06775 double *span_vector, *t, twice_area = 0.0;
06776 ON_3dPoint p0, p1;
06777 int degree, span_count, span_i, j;
06778 if ( !area )
06779 return false;
06780 *area = 0;
06781 if ( !curve )
06782 return false;
06783 const ON_PolyCurve* polycurve = ON_PolyCurve::Cast(curve);
06784 if ( polycurve )
06785 {
06786 span_count = polycurve->Count();
06787 ON_Interval span_domain, segment_curve_domain;
06788 double s0, s1;
06789 for ( span_i = 0; span_i < span_count; span_i++ )
06790 {
06791 span_domain = polycurve->SegmentDomain(span_i);
06792 if ( span_domain[1] <= curve_domain[0] )
06793 continue;
06794 if ( span_domain[0] >= curve_domain[1] )
06795 break;
06796 const ON_Curve* segment_curve = polycurve->SegmentCurve(span_i);
06797 segment_curve_domain = segment_curve->Domain();
06798 if ( curve_domain[0] > span_domain[0] || curve_domain[1] < span_domain[1] )
06799 {
06800 s0 = (curve_domain[0] > span_domain[0]) ? curve_domain[0] : span_domain[0];
06801 s1 = (curve_domain[1] < span_domain[1]) ? curve_domain[1] : span_domain[1];
06802 if ( segment_curve_domain != span_domain )
06803 {
06804 s0 = span_domain.NormalizedParameterAt(s0);
06805 s1 = span_domain.NormalizedParameterAt(s1);
06806 s0 = segment_curve_domain.ParameterAt(s0);
06807 s1 = segment_curve_domain.ParameterAt(s1);
06808 }
06809 segment_curve_domain.Set(s0,s1);
06810 }
06811 if ( !curve_area( start_point, segment_curve, segment_curve_domain, xform, &twice_area ) )
06812 {
06813 *area = 0.0;
06814 return false;
06815 }
06816 *area += twice_area;
06817 }
06818 }
06819 else
06820 {
06821 span_count = curve->SpanCount();
06822 if ( span_count < 1 )
06823 return false;
06824 degree = curve->Degree();
06825 if ( degree <= 1 )
06826 {
06827 degree = 1;
06828 }
06829 else if ( degree < 4)
06830 {
06831 degree = 4;
06832
06833
06834
06835
06836
06837 while ( span_count*degree < 16 )
06838 degree *= 2;
06839 }
06840
06841 span_vector = ws.GetDoubleMemory(span_count+1+degree);
06842 t = span_vector+(span_count+1);
06843 t[0] = 0.0;
06844 for ( j = 1; j < degree; j++ ) {
06845 t[j] = ((double)(j))/(degree);
06846 }
06847 if ( !curve->GetSpanVector( span_vector ) )
06848 return false;
06849
06850 p1 = xform ? (*xform)*start_point : start_point;
06851 for ( span_i = 0; span_i < span_count; span_i++ ) {
06852 span_domain.Set( span_vector[span_i], span_vector[span_i+1] );
06853 if ( span_domain[1] <= curve_domain[0] )
06854 continue;
06855 if ( span_domain[0] >= curve_domain[1] )
06856 break;
06857 if ( span_domain[1] > curve_domain[1] )
06858 span_domain.m_t[1] = curve_domain[1];
06859 if ( span_domain[0] < curve_domain[0] )
06860 span_domain.m_t[0] = curve_domain[0];
06861 if ( span_domain[0] >= span_domain[1] )
06862 continue;
06863 for ( j = 0; j < degree; j++ ) {
06864 p0 = p1;
06865 p1 = curve->PointAt(span_domain.ParameterAt(t[j]));
06866 if ( xform )
06867 p1 = (*xform)*p1;
06868 twice_area += (p0.x-p1.x)*(p0.y+p1.y);
06869 if ( !span_i && !j ) {
06870
06871 }
06872 }
06873 }
06874 p0 = p1;
06875 p1 = curve->PointAt(curve_domain[1]);
06876 twice_area += (p0.x-p1.x)*(p0.y+p1.y);
06877 start_point = p1;
06878 *area = 0.5*twice_area;
06879 }
06880
06881 return true;
06882 }
06883
06884 int ON_ClosedCurveOrientation( const ON_Curve& curve, const ON_Xform* xform )
06885 {
06886 int curve_orientation = 0;
06887 double area = 0.0;
06888 ON_3dPoint start_point = curve.PointAtEnd();
06889 const ON_Interval curve_domain = curve.Domain();
06890 if ( xform && xform->IsIdentity() )
06891 xform = 0;
06892 if (curve_area( start_point, &curve, curve_domain, xform, &area ))
06893 {
06894 double noise = 0.0;
06895 if ( area > noise )
06896 curve_orientation = 1;
06897 else if (area < noise )
06898 curve_orientation = -1;
06899 }
06900 return curve_orientation;
06901 }
06902
06903 static int loop_type_compar(const ON_BrepLoop *const* ppLoopA, const ON_BrepLoop *const* ppLoopB )
06904 {
06905 const ON_BrepLoop* loopA = *ppLoopA;
06906 const ON_BrepLoop* loopB = *ppLoopB;
06907 if ( loopA->m_type == loopB->m_type )
06908 return 0;
06909 if ( loopA->m_type == ON_BrepLoop::unknown )
06910 return 1;
06911 if ( loopB->m_type == ON_BrepLoop::unknown )
06912 return -1;
06913 if ( loopA->m_type < loopB->m_type )
06914 return -1;
06915 if ( loopA->m_type > loopB->m_type )
06916 return 1;
06917 return 0;
06918 }
06919
06920 bool ON_Brep::SortFaceLoops( ON_BrepFace& face ) const
06921 {
06922 int fli, li, loop_type;
06923 const int face_loop_count = face.m_li.Count();
06924 const int loop_count = m_L.Count();
06925 if ( face_loop_count < 1 || loop_count < 1 )
06926 return false;
06927 bool rc = true;
06928 ON_SimpleArray<const ON_BrepLoop*> loop_ptr(face_loop_count);
06929 for ( fli = 0; fli < face_loop_count; fli++ )
06930 {
06931 li = face.m_li[fli];
06932 if ( li < 0 || li >= loop_count )
06933 return false;
06934 const ON_BrepLoop& loop = m_L[li];
06935 if ( loop.m_loop_index != li )
06936 return false;
06937 loop_type = loop.m_type;
06938 if ( loop_type <= ON_BrepLoop::unknown || loop_type >= ON_BrepLoop::type_count )
06939 rc = false;
06940 loop_ptr.Append( &m_L[li] );
06941 }
06942 loop_ptr.QuickSort( loop_type_compar );
06943 for ( fli = 0; fli < face_loop_count; fli++ )
06944 {
06945 face.m_li[fli] = loop_ptr[fli]->m_loop_index;
06946 }
06947 return rc;
06948 }
06949
06950
06951 int
06952 ON_Brep::LoopDirection( const ON_BrepLoop& loop ) const
06953 {
06954 ON_3dPoint start_point;
06955 double d, a = 0.0;
06956 int ti, lti, c2i;
06957 const int brep_trim_count = m_T.Count();
06958 const int brep_C2_count = m_C2.Count();
06959 const int loop_trim_count = loop.m_ti.Count();
06960
06961 double noise = 0.0;
06962
06963
06964 for ( lti = 0; lti < loop_trim_count; lti++ ) {
06965 ti = loop.m_ti[lti];
06966 if ( ti < 0 || ti >= brep_trim_count ) {
06967 a = 0.0;
06968 break;
06969 }
06970 c2i = m_T[ti].m_c2i;
06971 if ( c2i < 0 || c2i >= brep_C2_count ) {
06972 a = 0.0;
06973 break;
06974 }
06975 if ( lti == 0 )
06976 {
06977
06978 if ( m_C2[c2i] )
06979 start_point = m_T[ti].PointAtStart();
06980 }
06981 if ( !curve_area( start_point, &m_T[ti], m_T[ti].Domain(), 0, &d ) ) {
06982 a = 0.0;
06983 break;
06984 }
06985
06986 a += d;
06987 }
06988
06989
06990
06991
06992 if (a > noise)
06993 return 1;
06994 else if (a < -noise)
06995 return -1;
06996 return 0;
06997 }
06998
06999 bool ON_Brep::SetVertexTolerances( ON_BOOL32 bLazy )
07000 {
07001 bool rc = true;
07002 int vi, vertex_count = m_V.Count();
07003 for ( vi = 0; vi < vertex_count; vi++ )
07004 {
07005 if ( !SetVertexTolerance( m_V[vi], bLazy ) )
07006 rc = false;
07007 }
07008 return rc;
07009 }
07010
07011 bool
07012 ON_Brep::SetVertexTolerance( ON_BrepVertex& vertex,
07013 ON_BOOL32 bLazySet
07014
07015
07016
07017
07018 ) const
07019 {
07020 if ( vertex.m_tolerance < 0.0 || !bLazySet ) {
07021 const int vertex_edge_count = vertex.EdgeCount();
07022 if ( vertex_edge_count < 1 ) {
07023 vertex.m_tolerance = 0.0;
07024 }
07025 else {
07026 vertex.m_tolerance = ON_UNSET_VALUE;
07027 double tolerance = 0.0;
07028 double d;
07029 ON_3dPoint uv;
07030 ON_Interval edge_domain;
07031
07032 const ON_Surface* s=0;
07033 int vei, ei, eti, endi;
07034 const int vertex_index = vertex.m_vertex_index;
07035 for ( vei = 0; vei < vertex_edge_count; vei++ )
07036 {
07037 ei = vertex.m_ei[vei];
07038 if ( ei < 0 )
07039 return false;
07040 const ON_BrepEdge& edge = m_E[ei];
07041 if ( !edge.ProxyCurve() )
07042 return false;
07043 edge_domain = edge.Domain();
07044 for ( endi = 0; endi < 2; endi++ )
07045 {
07046 if ( edge.m_vi[endi] == vertex_index )
07047 {
07048 d = vertex.point.DistanceTo( edge.PointAt(edge_domain[endi]) );
07049 if ( tolerance < d )
07050 tolerance = d;
07051 }
07052 }
07053 const int edge_trim_count = edge.m_ti.Count();
07054 for ( eti = 0; eti < edge_trim_count; eti++ )
07055 {
07056 const ON_BrepTrim* trim = Trim(edge.m_ti[eti]);
07057 if ( 0 == trim )
07058 continue;
07059 if ( 0 == trim->TrimCurveOf() )
07060 continue;
07061 s = trim->SurfaceOf();
07062 if ( 0 == s )
07063 continue;
07064 for ( endi = 0; endi < 2; endi++ ) {
07065 if ( edge.m_vi[endi] == vertex_index ) {
07066 uv = trim->PointAt( trim->Domain()[trim->m_bRev3d?1-endi:endi] );
07067 d = vertex.point.DistanceTo( s->PointAt(uv.x,uv.y) );
07068 if ( tolerance < d )
07069 tolerance = d;
07070 }
07071 }
07072 }
07073 }
07074 vertex.m_tolerance = (tolerance <= ON_ZERO_TOLERANCE) ? 0.0 : 1.001*tolerance;
07075 }
07076 }
07077 return (vertex.m_tolerance >= 0.0) ? true : false;
07078 }
07079
07080 bool
07081 ON_Brep::SetTrimTolerance( ON_BrepTrim& trim, ON_BOOL32 bLazy ) const
07082 {
07083
07084
07085 double ds, de, d;
07086 int dir, lti, prev_ti, next_ti;
07087 if ( trim.m_tolerance[0] < 0.0 || trim.m_tolerance[1] < 0.0 || !bLazy )
07088 {
07089
07090 if ( trim.m_li >= 0 && trim.m_li < m_L.Count() )
07091 {
07092 const ON_BrepLoop& loop = m_L[trim.m_li];
07093 const int loop_trim_count = loop.m_ti.Count();
07094 for ( lti = 0; lti < loop_trim_count; lti++ )
07095 {
07096 if ( loop.m_ti[lti] == trim.m_trim_index )
07097 {
07098 prev_ti = loop.m_ti[(lti-1+loop_trim_count)%loop_trim_count];
07099 next_ti = loop.m_ti[(lti+1)%loop_trim_count];
07100 if ( prev_ti >= 0 && next_ti >= 0 && prev_ti < m_T.Count() && next_ti < m_T.Count() )
07101 {
07102 const ON_BrepTrim& prev_trim = m_T[prev_ti];
07103 const ON_BrepTrim& next_trim = m_T[next_ti];
07104 const ON_Curve* prev_c2 = prev_trim.TrimCurveOf();
07105 const ON_Curve* next_c2 = next_trim.TrimCurveOf();
07106 const ON_Curve* c2 = trim.TrimCurveOf();
07107 if ( prev_c2 && c2 && next_c2 )
07108 {
07109 ON_3dPoint prev_end = prev_trim.PointAtEnd();
07110 ON_3dPoint this_start = trim.PointAtStart();
07111 ON_3dPoint this_end = trim.PointAtEnd();
07112 ON_3dPoint next_start = next_trim.PointAtStart();
07113 for ( dir = 0; dir < 2; dir++ )
07114 {
07115 if ( trim.m_tolerance[dir] < 0.0 || !bLazy )
07116 {
07117 ds = fabs(prev_end[dir] - this_start[dir] );
07118 de = fabs(this_end[dir] - next_start[dir] );
07119 d = (ds >= de) ? ds : de;
07120 trim.m_tolerance[dir] = ( d > ON_ZERO_TOLERANCE ) ? 1.001*d : 0.0;
07121 }
07122 }
07123 }
07124 }
07125 break;
07126 }
07127 }
07128 }
07129 }
07130 return (trim.m_tolerance[0] >= 0.0 && trim.m_tolerance[1] >= 0.0) ? true : false;
07131 }
07132
07133 bool
07134 ON_Brep::SetEdgeTolerance( ON_BrepEdge& edge, ON_BOOL32 bLazySet ) const
07135 {
07136 if ( edge.m_tolerance < 0.0 || !bLazySet )
07137 {
07138 const int edge_trim_count = edge.m_ti.Count();
07139 if ( edge_trim_count < 1 )
07140 {
07141 edge.m_tolerance = 0.0;
07142 }
07143 else
07144 {
07145 edge.m_tolerance = ON_UNSET_VALUE;
07146
07147
07148 }
07149 }
07150 return (edge.m_tolerance >= 0.0) ? true : false;
07151 }
07152
07153 bool ON_Brep::SetTrimTolerances( ON_BOOL32 bLazy )
07154 {
07155 bool rc = true;
07156 int ti, trim_count = m_T.Count();
07157 for ( ti = 0; ti < trim_count; ti++ )
07158 {
07159 if ( !SetTrimTolerance( m_T[ti], bLazy ) )
07160 rc = false;
07161 }
07162 return rc;
07163 }
07164
07165 bool ON_Brep::SetEdgeTolerances( ON_BOOL32 bLazy )
07166 {
07167 bool rc = true;
07168 int ei, edge_count = m_E.Count();
07169 for ( ei = 0; ei < edge_count; ei++ )
07170 {
07171 if ( !SetEdgeTolerance( m_E[ei], bLazy ) )
07172 rc = false;
07173 }
07174 return rc;
07175 }
07176
07177
07178 void ON_Brep::Dump( ON_TextLog& dump ) const
07179 {
07180 dump.Print("ON_Brep:\n");
07181
07182 if ( IsSurface() ) {
07183 dump.Print("(B-rep geometry is the same as underlying surface.)\n");
07184 }
07185
07186 dump.Print("surfaces: %d\n",m_S.Count());
07187 dump.Print("3d curve: %d\n",m_C3.Count());
07188 dump.Print("2d curves: %d\n",m_C2.Count());
07189 dump.Print("vertices: %d\n",m_V.Count());
07190 dump.Print("edges: %d\n",m_E.Count());
07191 dump.Print("trims: %d\n",m_T.Count());
07192 dump.Print("loops: %d\n",m_L.Count());
07193 dump.Print("faces: %d\n",m_F.Count());
07194
07195 int c2i;
07196 for ( c2i = 0; c2i < m_C2.Count(); c2i++ )
07197 {
07198 const ON_Curve* c2 = m_C2[c2i];
07199 if ( c2 )
07200 {
07201 ON_Interval cdom = c2->Domain();
07202 ON_3dPoint c_start, c_end;
07203 c_start = c2->PointAtStart();
07204 c_end = c2->PointAtEnd();
07205 const char* s = c2->ClassId()->ClassName();
07206 if ( !s )
07207 s = "";
07208 dump.Print("curve2d[%2d]: %s domain(%g,%g) start(%g,%g) end(%g,%g)\n",
07209 c2i, s, cdom[0], cdom[1],
07210 c_start.x, c_start.y,
07211 c_end.x, c_end.y);
07212 }
07213 else
07214 {
07215 dump.Print("curve2d[%2d]: NULL\n",c2i);
07216 }
07217 }
07218
07219 int c3i;
07220 for ( c3i = 0; c3i < m_C3.Count(); c3i++ )
07221 {
07222 const ON_Curve* c3 = m_C3[c3i];
07223 if ( c3 )
07224 {
07225 ON_Interval cdom = c3->Domain();
07226 ON_3dPoint c_start, c_end;
07227 c_start = c3->PointAtStart();
07228 c_end = c3->PointAtEnd();
07229 const char* s = c3->ClassId()->ClassName();
07230 if ( !s )
07231 s = "";
07232 dump.Print("curve3d[%2d]: %s domain(%g,%g) start(%g,%g,%g) end(%g,%g,%g)\n",
07233 c3i, s, cdom[0], cdom[1],
07234 c_start.x, c_start.y, c_start.z,
07235 c_end.x, c_end.y, c_end.z);
07236 }
07237 else
07238 {
07239 dump.Print("curve2d[%2d]: NULL\n",c3i);
07240 }
07241 }
07242
07243 int si;
07244 for ( si = 0; si < m_S.Count(); si++ )
07245 {
07246 const ON_Surface* srf = m_S[si];
07247 if ( srf )
07248 {
07249 ON_Interval udom = srf->Domain(0);
07250 ON_Interval vdom = srf->Domain(1);
07251 const char* s = srf->ClassId()->ClassName();
07252 if ( !s )
07253 s = "";
07254 dump.Print("surface[%2d]: %s u(%g,%g) v(%g,%g)\n",
07255 si, s,
07256 udom[0], udom[1],
07257 vdom[0], vdom[1]
07258 );
07259 if ( m_S.Count() == 1 && IsSurface() )
07260 {
07261 dump.PushIndent();
07262 dump.Print("surface details:\n");
07263 dump.PushIndent();
07264 srf->Dump(dump);
07265 dump.PopIndent();
07266 dump.PopIndent();
07267 }
07268 }
07269 else
07270 {
07271 dump.Print("surface[%2d]: NULL\n",si);
07272 }
07273 }
07274
07275 int vi;
07276 for ( vi = 0; vi < m_V.Count(); vi++ ) {
07277 const ON_BrepVertex& vertex = m_V[vi];
07278 dump.Print("vertex[%2d]: (%f %f %f) tolerance(%g)\n",
07279 vi,vertex.point.x,vertex.point.y,vertex.point.z,
07280 vertex.m_tolerance);
07281 if ( vertex.m_ei.Count() > 0 ) {
07282 int vei;
07283 dump.PushIndent();
07284 dump.Print("edges (");
07285 for ( vei = 0; vei < vertex.m_ei.Count(); vei++ ) {
07286 dump.Print( (vei)?",%d":"%d", vertex.m_ei[vei] );
07287 }
07288 dump.PopIndent();
07289 dump.Print(")\n");
07290 }
07291 }
07292
07293 int ei,ti;
07294 for ( ei = 0; ei < m_E.Count(); ei++ ) {
07295 const ON_BrepEdge& edge = m_E[ei];
07296 dump.Print("edge[%2d]: v0(%2d) v1(%2d) 3d_curve(%d) tolerance(%g)\n",
07297 ei,edge.m_vi[0],edge.m_vi[1],edge.m_c3i,edge.m_tolerance);
07298
07299 dump.PushIndent();
07300
07301 const ON_Curve* c3 = edge.EdgeCurveOf();
07302 if ( c3 )
07303 {
07304 ON_3dPoint edge_start = edge.PointAtStart();
07305 ON_3dPoint edge_end = edge.PointAtEnd();
07306 dump.Print("domain(%g,%g) start(%g,%g,%g) end(%g,%g,%g)\n",
07307 edge.Domain()[0],edge.Domain()[1],
07308 edge_start.x,edge_start.y,edge_start.z,
07309 edge_end.x,edge_end.y,edge_end.z
07310 );
07311 }
07312 else
07313 {
07314 dump.Print("domain(%g,%g) start(?,?,?) end(?,?,?)\n",
07315 edge.Domain()[0],edge.Domain()[1]);
07316 }
07317
07318 if ( edge.m_ti.Count() > 0 )
07319 {
07320
07321 dump.Print("trims (",edge.m_ti.Count());
07322 int eti;
07323 for ( eti = 0; eti < edge.m_ti.Count(); eti++ )
07324 {
07325 ti = edge.m_ti[eti];
07326 const char* sign = "?";
07327 if ( ti >= 0 && ti < m_T.Count() ) {
07328 sign = m_T[ti].m_bRev3d ? "-" : "+";
07329 }
07330 dump.Print( (eti)?",%s%d":"%s%d", sign,edge.m_ti[eti]);
07331 }
07332
07333 dump.Print(")\n");
07334 }
07335
07336 dump.PopIndent();
07337 }
07338
07339 int fi;
07340 for ( fi = 0; fi < m_F.Count(); fi++ ) {
07341 const ON_BrepFace& face = m_F[fi];
07342 const ON_Surface* face_srf = face.SurfaceOf();
07343 dump.Print("face[%2d]: surface(%d) reverse(%d) loops(",
07344 fi,face.m_si,face.m_bRev);
07345 int fli;
07346 for ( fli = 0; fli < face.m_li.Count(); fli++ ) {
07347 dump.Print( (fli)?",%d":"%d", face.m_li[fli]);
07348 }
07349 dump.Print(")\n");
07350 dump.PushIndent();
07351 if ( face.m_render_mesh )
07352 {
07353 const char* mp_style = "Custom";
07354 const ON_MeshParameters* mp = face.m_render_mesh->MeshParameters();
07355 if ( mp )
07356 {
07357 if ( 0 == mp->CompareGeometrySettings(ON_MeshParameters::FastRenderMesh) )
07358 mp_style = "Fast";
07359 else if ( 0 == mp->CompareGeometrySettings(ON_MeshParameters::QualityRenderMesh) )
07360 mp_style = "Quality";
07361 }
07362 dump.Print("%s render mesh: %d polygons\n",mp_style,face.m_render_mesh->FaceCount());
07363 }
07364 if ( face.m_analysis_mesh ) {
07365 dump.Print("Analysis mesh: %d polygons\n",face.m_analysis_mesh->FaceCount());
07366 }
07367 if ( FaceIsSurface(fi) ) {
07368 dump.Print("(Face geometry is the same as underlying surface.)\n");
07369 }
07370
07371
07372 for ( fli = 0; fli < face.m_li.Count(); fli++ )
07373 {
07374 const int li = face.m_li[fli];
07375 const ON_BrepLoop& loop = m_L[li];
07376 const char* sLoopType = 0;
07377 switch( loop.m_type )
07378 {
07379 case ON_BrepLoop::unknown:
07380 sLoopType = "unknown";
07381 break;
07382 case ON_BrepLoop::outer:
07383 sLoopType = "outer";
07384 break;
07385 case ON_BrepLoop::inner:
07386 sLoopType = "inner";
07387 break;
07388 case ON_BrepLoop::slit:
07389 sLoopType = "slit";
07390 break;
07391 case ON_BrepLoop::crvonsrf:
07392 sLoopType = "crvonsrf";
07393 break;
07394 default:
07395 sLoopType = "unknown";
07396 break;
07397 }
07398 dump.Print("loop[%2d]: type(%s) %d trims(",
07399 li, sLoopType, loop.m_ti.Count());
07400 int lti;
07401 for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
07402 {
07403 dump.Print( (lti)?",%d":"%d", loop.m_ti[lti]);
07404 }
07405 dump.Print(")\n");
07406 dump.PushIndent();
07407 for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
07408 {
07409 const int ti = loop.m_ti[lti];
07410 const ON_BrepTrim& trim = m_T[ti];
07411 const char* sTrimType = "?";
07412 const char* sTrimIso = "-?";
07413 const ON_Curve* c2 = trim.TrimCurveOf();
07414 ON_3dPoint trim_start, trim_end;
07415 switch( trim.m_type ) {
07416 case ON_BrepTrim::unknown:
07417 sTrimType = "unknown ";
07418 break;
07419 case ON_BrepTrim::boundary:
07420 sTrimType = "boundary";
07421 break;
07422 case ON_BrepTrim::mated:
07423 sTrimType = "mated ";
07424 break;
07425 case ON_BrepTrim::seam:
07426 sTrimType = "seam ";
07427 break;
07428 case ON_BrepTrim::singular:
07429 sTrimType = "singular";
07430 break;
07431 case ON_BrepTrim::crvonsrf:
07432 sTrimType = "crvonsrf";
07433 break;
07434 default:
07435 sTrimType = "unknown";
07436 break;
07437 }
07438 switch( trim.m_iso ) {
07439 case ON_Surface::not_iso:
07440 sTrimIso = "";
07441 break;
07442 case ON_Surface::x_iso:
07443 sTrimIso = "-u iso";
07444 break;
07445 case ON_Surface::W_iso:
07446 sTrimIso = "-west side iso";
07447 break;
07448 case ON_Surface::E_iso:
07449 sTrimIso = "-east side iso";
07450 break;
07451 case ON_Surface::y_iso:
07452 sTrimIso = "-v iso";
07453 break;
07454 case ON_Surface::S_iso:
07455 sTrimIso = "-south side iso";
07456 break;
07457 case ON_Surface::N_iso:
07458 sTrimIso = "-north side iso";
07459 break;
07460 default:
07461 sTrimIso = "-unknown_iso_flag";
07462 break;
07463 }
07464 dump.Print("trim[%2d]: edge(%2d) v0(%2d) v1(%2d) tolerance(%g,%g)\n",
07465 ti,
07466 trim.m_ei,trim.m_vi[0],trim.m_vi[1],
07467 trim.m_tolerance[0],trim.m_tolerance[1]);
07468 dump.PushIndent();
07469 dump.Print("type(%s%s) rev3d(%d) 2d_curve(%d)\n",
07470 sTrimType, sTrimIso, trim.m_bRev3d, trim.m_c2i);
07471 if ( c2 )
07472 {
07473 trim_start = trim.PointAtStart();
07474 trim_end = trim.PointAtEnd();
07475 dump.Print("domain(%g,%g) start(%g,%g) end(%g,%g)\n",
07476 trim.Domain()[0],trim.Domain()[1],
07477 trim_start.x,trim_start.y,
07478 trim_end.x,trim_end.y);
07479 if ( 0 != face_srf )
07480 {
07481 ON_3dPoint trim_srfstart = face_srf->PointAt(trim_start.x,trim_start.y);
07482 ON_3dPoint trim_srfend = face_srf->PointAt(trim_end.x,trim_end.y);
07483 dump.Print("surface points start(%g,%g,%g) end(%g,%g,%g)\n",
07484 trim_srfstart.x,trim_srfstart.y,trim_srfstart.z,
07485 trim_srfend.x,trim_srfend.y,trim_srfend.z);
07486 }
07487 }
07488 else
07489 {
07490 dump.Print("domain(%g,%g) start(?,?) end(?,?)\n",
07491 trim.Domain()[0],trim.Domain()[1]);
07492 }
07493 dump.PopIndent();
07494 }
07495 dump.PopIndent();
07496 }
07497 dump.PopIndent();
07498 }
07499
07500
07501
07502
07503
07504
07505
07506
07507
07508
07509
07510
07511 }
07512
07513
07514
07515
07516
07517
07518
07519
07520
07521
07522
07523
07524
07525
07526
07527
07528
07529
07530
07531
07532
07533
07534
07535
07536
07537
07538
07539
07540
07541
07542
07543
07544
07545
07546
07547
07548
07549
07550
07551
07552
07553
07554
07555
07556
07557
07558
07559
07560
07561
07562
07563
07564
07565
07566
07567
07568
07569
07570
07571
07572
07573
07574
07575
07576
07577
07578
07579
07580
07581
07582
07583
07584
07585
07586
07587
07588
07589
07590
07591
07592
07593
07594
07595
07596
07597
07598
07599
07600
07601
07602
07603
07604
07605
07606
07607
07608
07609
07610
07611
07612
07613
07614
07615
07616
07617
07618 void ON_Brep::DeleteVertex(ON_BrepVertex& vertex)
07619 {
07620 const int vi = vertex.m_vertex_index;
07621 vertex.m_vertex_index = -1;
07622 if ( vi >= 0 && vi < m_V.Count() ) {
07623 int vei, ei;
07624 for ( vei = vertex.m_ei.Count()-1; vei>=0; vei-- ) {
07625 ei = vertex.m_ei[vei];
07626 if ( ei >= 0 && ei < m_E.Count() ) {
07627 ON_BrepEdge& edge = m_E[ei];
07628 if ( edge.m_vi[0] == vi )
07629 edge.m_vi[0] = -1;
07630 if ( edge.m_vi[1] == vi )
07631 edge.m_vi[1] = -1;
07632 DeleteEdge( edge, false );
07633 }
07634 }
07635 }
07636 vertex.m_ei.Empty();
07637 vertex.m_tolerance = ON_UNSET_VALUE;
07638 }
07639
07640 int ON_Brep::Loop3dCurve(
07641 const ON_BrepLoop& loop,
07642 ON_SimpleArray<ON_Curve*>& curve_list,
07643 ON_BOOL32 bRevCurveIfFaceRevIsTrue
07644 ) const
07645 {
07646 int curve_list_count0 = curve_list.Count();
07647 ON_PolyCurve* poly_curve = NULL;
07648 ON_Curve* loop_curve = NULL;
07649 ON_SimpleArray<int> trim_index( 2*loop.m_ti.Count() + 8);
07650 int i, lti, ti;
07651 int loop_trim_count = loop.m_ti.Count();
07652 if ( loop_trim_count < 1 )
07653 return 0;
07654
07655
07656 int seam_lti = -1;
07657 int wire_lti = -1;
07658 for ( lti = 0; lti < loop_trim_count; lti++ )
07659 {
07660 ti = loop.m_ti[lti];
07661 if ( ti >= 0 && ti < m_T.Count() )
07662 {
07663 const ON_BrepTrim& trim = m_T[ti];
07664 if ( seam_lti < 0 && trim.m_type == ON_BrepTrim::seam )
07665 seam_lti = lti;
07666 else if ( wire_lti < 0 && trim.m_type != ON_BrepTrim::singular )
07667 wire_lti = lti;
07668 }
07669 }
07670
07671 if ( wire_lti < 0 )
07672 return 0;
07673
07674 if ( seam_lti < 0 )
07675 {
07676
07677 loop_curve = Loop3dCurve(loop,bRevCurveIfFaceRevIsTrue);
07678 if ( loop_curve )
07679 curve_list.Append(loop_curve);
07680 return curve_list.Count() - curve_list_count0;
07681 }
07682
07683 bool bOnSeam = true;
07684 for ( lti = seam_lti; lti < seam_lti+loop_trim_count; lti++ )
07685 {
07686 ti = loop.m_ti[lti%loop_trim_count];
07687
07688 if ( ti < 0 || ti >= m_T.Count() )
07689 ti = loop.m_ti[seam_lti];
07690
07691 const ON_BrepTrim& trim = m_T[ti];
07692 if ( trim.m_type == ON_BrepTrim::seam )
07693 {
07694 if (!bOnSeam)
07695 {
07696 trim_index.Append(-1);
07697 bOnSeam = true;
07698 }
07699 continue;
07700 }
07701
07702 if ( trim.m_type == ON_BrepTrim::singular )
07703 continue;
07704 bOnSeam = false;
07705 trim_index.Append(ti);
07706 }
07707
07708 for ( i = 0; i < trim_index.Count(); i++ )
07709 {
07710 ti = trim_index[i];
07711 if ( ti < 0 )
07712 {
07713 if ( loop_curve )
07714 curve_list.Append(loop_curve);
07715 loop_curve = 0;
07716 poly_curve = 0;
07717 continue;
07718 }
07719
07720
07721 const ON_BrepTrim& trim = m_T[ti];
07722 const ON_BrepEdge& edge = m_E[trim.m_ei];
07723 ON_Curve* segment_curve = edge.DuplicateCurve();
07724 if ( !segment_curve )
07725 continue;
07726 if ( trim.m_bRev3d )
07727 segment_curve->Reverse();
07728
07729 if ( !loop_curve )
07730 loop_curve = segment_curve;
07731 else if ( !poly_curve )
07732 {
07733 poly_curve = new ON_PolyCurve();
07734 poly_curve->Append(loop_curve);
07735 poly_curve->Append(segment_curve);
07736 loop_curve = poly_curve;
07737 }
07738 else
07739 poly_curve->Append( segment_curve );
07740 }
07741
07742
07743 if ( loop_curve )
07744 curve_list.Append(loop_curve);
07745
07746 if ( bRevCurveIfFaceRevIsTrue )
07747 {
07748 int fi = loop.m_fi;
07749 if ( fi >= 0 && fi < m_F.Count() && m_F[fi].m_bRev )
07750 {
07751 for ( i = curve_list_count0; i < curve_list.Count(); i++ )
07752 curve_list[i]->Reverse();
07753 }
07754 }
07755
07756 return curve_list.Count() - curve_list_count0;
07757 }
07758
07759
07760 ON_Curve* ON_Brep::Loop3dCurve( const ON_BrepLoop& loop, ON_BOOL32 bRevCurveIfFaceRevIsTrue ) const
07761 {
07762 ON_PolyCurve* poly_curve = NULL;
07763 ON_Curve* loop_curve = NULL;
07764 ON_SimpleArray<int> trim_index( loop.m_ti.Count() );
07765 int i, lti, ti;
07766 for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
07767 {
07768 ti = loop.m_ti[lti];
07769 if ( ti >= 0 && ti < m_T.Count() )
07770 {
07771 const ON_BrepTrim& trim = m_T[ti];
07772 if ( trim.EdgeCurveOf() )
07773 trim_index.Append(ti);
07774 }
07775 }
07776
07777 for ( i = 0; i < trim_index.Count(); i++ )
07778 {
07779
07780 const ON_BrepTrim& trim = m_T[trim_index[i]];
07781 const ON_BrepEdge& edge = m_E[trim.m_ei];
07782 ON_Curve* segment_curve = edge.DuplicateCurve();
07783 if ( !segment_curve )
07784 continue;
07785 if ( trim.m_bRev3d )
07786 segment_curve->Reverse();
07787
07788 if ( !loop_curve )
07789 loop_curve = segment_curve;
07790 else if ( !poly_curve )
07791 {
07792 poly_curve = new ON_PolyCurve();
07793 poly_curve->Append(loop_curve);
07794 poly_curve->Append(segment_curve);
07795 loop_curve = poly_curve;
07796 }
07797 else
07798 poly_curve->Append( segment_curve );
07799 }
07800 if ( loop_curve && bRevCurveIfFaceRevIsTrue )
07801 {
07802 int fi = loop.m_fi;
07803 if ( fi >= 0 && fi < m_F.Count() && m_F[fi].m_bRev )
07804 {
07805 loop_curve->Reverse();
07806 }
07807 }
07808 return loop_curve;
07809 }
07810
07811 ON_Curve* ON_Brep::Loop2dCurve( const ON_BrepLoop& loop ) const
07812 {
07813 ON_PolyCurve* poly_curve = NULL;
07814 ON_Curve* loop_curve = NULL;
07815 ON_SimpleArray<int> trim_index( loop.m_ti.Count() );
07816 int i, lti, ti;
07817 for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
07818 {
07819 ti = loop.m_ti[lti];
07820 if ( ti >= 0 && ti < m_T.Count() )
07821 {
07822 const ON_BrepTrim& trim = m_T[ti];
07823 if ( trim.TrimCurveOf() )
07824 trim_index.Append(ti);
07825 }
07826 }
07827 for ( i = 0; i < trim_index.Count(); i++ )
07828 {
07829
07830 const ON_BrepTrim& trim = m_T[trim_index[i]];
07831 ON_Curve* segment_curve = trim.DuplicateCurve();
07832 if ( !segment_curve )
07833 continue;
07834
07835 if ( !loop_curve )
07836 loop_curve = segment_curve;
07837 else if ( !poly_curve )
07838 {
07839 poly_curve = new ON_PolyCurve();
07840 poly_curve->Append(loop_curve);
07841 poly_curve->Append(segment_curve);
07842 loop_curve = poly_curve;
07843 }
07844 else
07845 poly_curve->Append( segment_curve );
07846 }
07847 return loop_curve;
07848 }
07849
07850
07851
07852 void ON_Brep::DeleteEdge(ON_BrepEdge& edge, ON_BOOL32 bDeleteEdgeVertices )
07853 {
07854 const int ei = edge.m_edge_index;
07855 edge.m_edge_index = -1;
07856
07857 if ( ei >= 0 && ei < m_E.Count() ) {
07858 int eti, ti, evi, vei, vi;
07859 for ( eti = edge.m_ti.Count()-1; eti >= 0; eti-- ) {
07860 ti = edge.m_ti[eti];
07861 if ( ti >= 0 && ti < m_T.Count() ) {
07862 ON_BrepTrim& trim = m_T[ti];
07863 trim.m_ei = -1;
07864 if ( trim.m_li >= 0 && trim.m_li < m_L.Count() ) {
07865 ON_BrepLoop& loop = m_L[trim.m_li];
07866 if ( loop.m_fi >= 0 && loop.m_fi < m_F.Count() ) {
07867 DeleteFace( m_F[loop.m_fi], bDeleteEdgeVertices );
07868 }
07869 }
07870 DeleteTrim(trim,false);
07871 }
07872 }
07873
07874 for (evi = 0; evi < 2; evi++ )
07875 {
07876 vi = edge.m_vi[evi];
07877 if ( vi >= 0 && vi < m_V.Count() )
07878 {
07879 ON_BrepVertex& v = m_V[vi];
07880 for ( vei = v.m_ei.Count()-1; vei >= 0; vei-- )
07881 {
07882 if ( v.m_ei[vei] == ei )
07883 v.m_ei.Remove(vei);
07884 }
07885 if ( bDeleteEdgeVertices && v.m_ei.Count() <= 0 )
07886 {
07887 v.m_ei.Destroy();
07888 DeleteVertex(v);
07889 }
07890 }
07891 }
07892 }
07893
07894 edge.m_c3i = -1;
07895 edge.m_vi[0] = -1;
07896 edge.m_vi[1] = -1;
07897 edge.m_ti.Empty();
07898 edge.m_tolerance = ON_UNSET_VALUE;
07899 edge.m_brep = 0;
07900 edge.SetProxyCurve(0);
07901 }
07902
07903 void ON_Brep::DeleteTrim(ON_BrepTrim& trim, ON_BOOL32 bDeleteTrimEdges )
07904 {
07905 m_is_solid = 0;
07906
07907 const int ti = trim.m_trim_index;
07908 trim.m_trim_index = -1;
07909
07910 if ( ti >= 0 && ti < m_T.Count() )
07911 {
07912 const int ei = trim.m_ei;
07913 if ( ei >= 0 && ei < m_E.Count() )
07914 {
07915 ON_BrepEdge& edge = m_E[ei];
07916 if ( bDeleteTrimEdges && edge.m_ti.Count() == 1 && edge.m_ti[0] == ti )
07917 {
07918 edge.m_ti.Empty();
07919 DeleteEdge(edge,bDeleteTrimEdges);
07920 }
07921 else
07922 {
07923 int mate_ti = (trim.m_type == ON_BrepTrim::mated) ? -1 : -2;
07924 int seam_ti = (trim.m_type == ON_BrepTrim::seam) ? -1 : -2;
07925 int eti;
07926 for ( eti = edge.m_ti.Count()-1; eti >= 0; eti-- )
07927 {
07928 int other_ti = edge.m_ti[eti];
07929 if ( other_ti == ti )
07930 {
07931 edge.m_ti.Remove(eti);
07932 if ( edge.m_ti.Count() == 0 )
07933 edge.m_tolerance = 0.0;
07934 continue;
07935 }
07936
07937 if ( (mate_ti >= -1 || seam_ti >= -1 ) && other_ti >= 0 && other_ti < m_T.Count() )
07938 {
07939 const ON_BrepTrim& other_trim = m_T[other_ti];
07940 if ( other_trim.m_trim_index != other_ti )
07941 continue;
07942 if ( mate_ti >= -1 && other_trim.m_type == ON_BrepTrim::mated )
07943 {
07944
07945 if ( mate_ti == -1 )
07946 mate_ti = other_ti;
07947 else
07948 mate_ti = -2;
07949 }
07950 else if ( seam_ti >= -1 && other_trim.m_type == ON_BrepTrim::seam && other_trim.m_li == trim.m_li )
07951 {
07952
07953
07954 if ( seam_ti == -1 )
07955 seam_ti = other_ti;
07956 else
07957 seam_ti = -2;
07958 }
07959 }
07960 }
07961
07962 if ( seam_ti >= 0 )
07963 {
07964
07965
07966 m_T[seam_ti].m_type = (mate_ti>=0)
07967 ? ON_BrepTrim::mated
07968 : ON_BrepTrim::boundary;
07969 }
07970 else if ( mate_ti >= 0 )
07971 {
07972
07973 m_T[mate_ti].m_type = ON_BrepTrim::boundary;
07974 }
07975 }
07976 }
07977
07978 const int li = trim.m_li;
07979 if ( li >= 0 && li < m_L.Count() ) {
07980 ON_BrepLoop& loop = m_L[li];
07981 int lti;
07982 for ( lti = loop.m_ti.Count()-1; lti >= 0; lti-- ) {
07983 if ( loop.m_ti[lti] == ti )
07984 loop.m_ti.Remove(lti);
07985 }
07986 }
07987 }
07988
07989 trim.m_c2i = -1;
07990 trim.m_ei = -1;
07991 trim.m_vi[0] = -1;
07992 trim.m_vi[1] = -1;
07993 trim.m_bRev3d = 0;
07994 trim.m_type = ON_BrepTrim::unknown;
07995 trim.m_iso = ON_Surface::not_iso;
07996 trim.m_li = -1;
07997 trim.m_tolerance[0] = ON_UNSET_VALUE;
07998 trim.m_tolerance[1] = ON_UNSET_VALUE;
07999 trim.m__legacy_2d_tol = ON_UNSET_VALUE;
08000 trim.m__legacy_3d_tol = ON_UNSET_VALUE;
08001 trim.m__legacy_flags = 0;
08002 trim.m_pbox.Destroy();
08003 trim.m_brep = 0;
08004 trim.SetProxyCurve(0);
08005 }
08006
08007 void ON_Brep::DeleteLoop(ON_BrepLoop& loop, ON_BOOL32 bDeleteLoopEdges )
08008 {
08009 m_is_solid = 0;
08010
08011 const int li = loop.m_loop_index;
08012 loop.m_loop_index = -1;
08013
08014 if ( loop.m_fi >= 0 )
08015 DestroyMesh(ON::any_mesh,true);
08016
08017 if ( li >= 0 && li < m_L.Count() )
08018 {
08019 const int tcount = m_T.Count();
08020 int lti, ti;
08021 for ( lti = loop.m_ti.Count()-1; lti >= 0; lti-- )
08022 {
08023 ti = loop.m_ti[lti];
08024 if ( ti >= 0 && ti < tcount )
08025 {
08026 ON_BrepTrim& trim = m_T[ti];
08027 trim.m_li = -1;
08028 DeleteTrim(trim,bDeleteLoopEdges);
08029 }
08030 }
08031
08032 const int fi = loop.m_fi;
08033 if ( fi >= 0 && fi < m_F.Count() )
08034 {
08035 ON_BrepFace& face = m_F[fi];
08036 int fli;
08037 for ( fli = face.m_li.Count()-1; fli >= 0; fli-- )
08038 {
08039 if ( face.m_li[fli] == li )
08040 {
08041 face.m_li.Remove(fli);
08042 }
08043 }
08044 }
08045 }
08046
08047 loop.m_type = ON_BrepLoop::unknown;
08048 loop.m_ti.Empty();
08049 loop.m_fi = -1;
08050 loop.m_pbox.Destroy();
08051 loop.m_brep = 0;
08052 }
08053
08054 void ON_Brep::DeleteFace(ON_BrepFace& face, ON_BOOL32 bDeleteFaceEdges )
08055 {
08056 m_bbox.Destroy();
08057 m_is_solid = 0;
08058
08059 const int fi = face.m_face_index;
08060 face.m_face_index = -1;
08061
08062 if ( fi >= 0 && fi < m_F.Count() ) {
08063 const int lcount = m_L.Count();
08064 int fli, li;
08065 for ( fli = face.m_li.Count()-1; fli >= 0; fli-- ) {
08066 li = face.m_li[fli];
08067 if ( li >= 0 && li < lcount ) {
08068 ON_BrepLoop& loop = m_L[li];
08069 loop.m_fi = -1;
08070 DeleteLoop(loop,bDeleteFaceEdges);
08071 }
08072 }
08073 }
08074
08075 face.m_si = -1;
08076 face.m_li.Empty();
08077 face.SetProxySurface(0);
08078 face.m_brep = 0;
08079 face.m_bbox.Destroy();
08080 }
08081
08082 static void PropagateLabel(ON_Brep& B,
08083 ON_SimpleArray<int>& fids,
08084 int label
08085 )
08086
08087 {
08088 if (fids.Count() == 0) return;
08089 ON_SimpleArray<int> new_fids(B.m_F.Count());
08090 for (int face_i=0; face_i<fids.Count(); face_i++)
08091 {
08092 const ON_BrepFace& F = B.m_F[fids[face_i]];
08093 for (int loop_i=0; loop_i<F.m_li.Count(); loop_i++)
08094 {
08095 ON_BrepLoop& L = B.m_L[F.m_li[loop_i]];
08096 memset(&L.m_loop_user,0,sizeof(L.m_loop_user));
08097 L.m_loop_user.i = label;
08098 for (int edge_i=0; edge_i<L.m_ti.Count(); edge_i++)
08099 {
08100 ON_BrepTrim& T = B.m_T[L.m_ti[edge_i]];
08101 memset(&T.m_trim_user,0,sizeof(T.m_trim_user));
08102 T.m_trim_user.i = label;
08103 if (T.m_ei < 0)
08104 continue;
08105 ON_BrepEdge& E = B.m_E[T.m_ei];
08106 memset(&E.m_edge_user,0,sizeof(E.m_edge_user));
08107 E.m_edge_user.i = label;
08108 for (int vertex_i=0; vertex_i<2; vertex_i++)
08109 {
08110 if (E.m_vi[vertex_i] >= 0)
08111 {
08112 ON_BrepVertex& V = B.m_V[E.m_vi[vertex_i]];
08113 memset(&V.m_vertex_user,0,sizeof(V.m_vertex_user));
08114 V.m_vertex_user.i = label;
08115 }
08116 }
08117
08118 for (int trim_i=0; trim_i<E.m_ti.Count(); trim_i++)
08119 {
08120 int fi = B.m_T[E.m_ti[trim_i]].FaceIndexOf();
08121 if (fi < 0 || B.m_F[fi].m_face_user.i == label)
08122 continue;
08123 ON_BrepFace& F = B.m_F[fi];
08124 memset(&F.m_face_user,0,sizeof(F.m_face_user));
08125 F.m_face_user.i = label;
08126 new_fids.Append(fi);
08127 }
08128 }
08129 }
08130 }
08131 PropagateLabel(B, new_fids, label);
08132 return;
08133 }
08134
08135
08136 void ON_Brep::LabelConnectedComponent(int face_index, int label)
08137
08138 {
08139 if (face_index < 0 || face_index >= m_F.Count())
08140 return;
08141
08142 ON_SimpleArray<int> fids(1);
08143 fids.Append(face_index);
08144 ON_BrepFace& F = m_F[face_index];
08145 memset(&F.m_face_user,0,sizeof(F.m_face_user));
08146 F.m_face_user.i = label;
08147 PropagateLabel(*this, fids, label);
08148 return;
08149 }
08150
08151 int ON_Brep::LabelConnectedComponents()
08152
08153 {
08154 Clear_user_i();
08155 int i;
08156 for (i=0; i<m_F.Count(); i++){
08157 if (m_F[i].m_face_index < 0)
08158 m_F[i].m_face_user.i = -1;
08159 }
08160
08161 int label = 0;
08162 bool keep_going = true;
08163 while (keep_going)
08164 {
08165 int face_index = -1;
08166 for (int j=0; j<m_F.Count(); j++)
08167 {
08168 if (m_F[j].m_face_user.i == 0)
08169 {
08170 face_index = j;
08171 break;
08172 }
08173 }
08174 if (face_index == -1)
08175 {
08176 keep_going = false;
08177 continue;
08178 }
08179 label++;
08180 LabelConnectedComponent(face_index, label);
08181 }
08182 return label;
08183 }
08184
08185 int ON_Brep::GetConnectedComponents( ON_SimpleArray< ON_Brep* >& components, bool bDuplicateMeshes ) const
08186 {
08187 const int count0 = components.Count();
08188 ON_Brep brep(*this);
08189 int count = brep.LabelConnectedComponents();
08190 if ( count > 1 )
08191 {
08192 int cci;
08193 ON_SimpleArray<int> fi(brep.m_F.Count());
08194 for ( cci = 1; cci <= count; cci++ )
08195 {
08196 fi.SetCount(0);
08197 for ( int j = 0; j < brep.m_F.Count(); j++ )
08198 {
08199 if ( brep.m_F[j].m_face_user.i == cci )
08200 fi.Append(j);
08201 }
08202 if ( fi.Count() > 0 )
08203 {
08204 ON_Brep* cc = brep.DuplicateFaces( fi.Count(), fi.Array(), bDuplicateMeshes );
08205 if ( cc )
08206 components.Append(cc);
08207 }
08208 }
08209 }
08210
08211 return components.Count() - count0;
08212 }
08213
08214 ON_Brep* ON_Brep::DuplicateFace( int face_index, ON_BOOL32 bDuplicateMeshes ) const
08215 {
08216 return DuplicateFaces( 1, &face_index, bDuplicateMeshes );
08217 }
08218
08219 ON_Brep* ON_Brep::DuplicateFaces( int face_count, const int* face_index, ON_BOOL32 bDuplicateMeshes ) const
08220 {
08221 int fi, si, fli, lti, li, ti, i;
08222 ON_BOOL32 rc = false;
08223 ON_Brep* brep_copy = 0;
08224 ON_Object* dup = 0;
08225
08226
08227 ON_SimpleArray<int> s_remap(m_S.Count());
08228 s_remap.SetCount(m_S.Count());
08229 s_remap.Zero();
08230 ON_SimpleArray<int> f_remap(m_F.Count());
08231 f_remap.SetCount(m_F.Count());
08232 f_remap.Zero();
08233 ON_SimpleArray<int> c2_remap(m_C2.Count());
08234 c2_remap.SetCount(m_C2.Count());
08235 c2_remap.Zero();
08236 ON_SimpleArray<int> c3_remap(m_C3.Count());
08237 c3_remap.SetCount(m_C3.Count());
08238 c3_remap.Zero();
08239 ON_SimpleArray<int> e_remap(m_E.Count());
08240 e_remap.SetCount(m_E.Count());
08241 e_remap.Zero();
08242 ON_SimpleArray<int> v_remap(m_V.Count());
08243 v_remap.SetCount(m_V.Count());
08244 v_remap.Zero();
08245 for (i = 0; i < face_count; i++ ) {
08246 fi = face_index[i];
08247 if (fi >= 0 && fi < m_F.Count() ) {
08248 const ON_BrepFace& face = m_F[fi];
08249 rc = true;
08250 f_remap[fi] = 1;
08251 si = face.m_si;
08252 if ( si >= 0 && si < m_S.Count() ) {
08253 s_remap[si] = 1;
08254 }
08255 for ( fli = 0; fli < face.m_li.Count(); fli++ )
08256 {
08257 li = face.m_li[fli];
08258 if ( li < 0 || li >= m_L.Count() )
08259 continue;
08260 const ON_BrepLoop& loop = m_L[li];
08261 for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
08262 {
08263 ti = loop.m_ti[lti];
08264 if ( ti < 0 || ti >= m_T.Count() )
08265 continue;
08266 const ON_BrepTrim& trim = m_T[ti];
08267 if ( trim.m_ei >= 0 && trim.m_ei < m_E.Count() )
08268 {
08269 int vi;
08270 e_remap[trim.m_ei] = 1;
08271 vi = m_E[trim.m_ei].m_vi[0];
08272 if ( vi >= 0 )
08273 v_remap[vi] = 1;
08274 vi = m_E[trim.m_ei].m_vi[1];
08275 if ( vi >= 0 )
08276 v_remap[vi] = 1;
08277 }
08278 if ( trim.m_vi[0] >= 0 )
08279 v_remap[trim.m_vi[0]] = 1;
08280 if ( trim.m_vi[1] >= 0 )
08281 v_remap[trim.m_vi[1]] = 1;
08282 int ci = trim.EdgeCurveIndexOf();
08283 if ( ci >= 0 ) {
08284 c3_remap[ci] = 1;
08285 }
08286 ci = trim.TrimCurveIndexOf();
08287 if ( ci >= 0 )
08288 c2_remap[ci] = 1;
08289 }
08290 }
08291 }
08292 }
08293 if ( !rc )
08294 return NULL;
08295
08296 brep_copy = new ON_Brep();
08297
08298
08299 for ( i = 0; i < m_S.Count() && rc; i++ )
08300 {
08301 if ( s_remap[i] ) {
08302 if ( !m_S[i] )
08303 break;
08304 dup = m_S[i]->Duplicate();
08305 ON_Surface* srf_copy = ON_Surface::Cast(dup);
08306 if ( !srf_copy )
08307 break;
08308 s_remap[i] = brep_copy->AddSurface(srf_copy);
08309 dup = 0;
08310 }
08311 else
08312 s_remap[i] = -1;
08313 }
08314 rc = ( rc && i == m_S.Count() );
08315
08316
08317 for ( i = 0; i < m_C2.Count() && rc; i++ )
08318 {
08319 if ( c2_remap[i] ) {
08320 if ( !m_C2[i] )
08321 break;
08322 dup = m_C2[i]->Duplicate();
08323 ON_Curve* crv_copy = ON_Curve::Cast(dup);
08324 if ( !crv_copy )
08325 break;
08326 c2_remap[i] = brep_copy->AddTrimCurve(crv_copy);
08327 dup = 0;
08328 }
08329 else
08330 c2_remap[i] = -1;
08331 }
08332 rc = ( rc && i == m_C2.Count() );
08333
08334
08335 for ( i = 0; i < m_C3.Count() && rc; i++ )
08336 {
08337 if ( c3_remap[i] ) {
08338 if ( !m_C3[i] )
08339 break;
08340 dup = m_C3[i]->Duplicate();
08341 ON_Curve* crv_copy = ON_Curve::Cast(dup);
08342 if ( !crv_copy )
08343 break;
08344 c3_remap[i] = brep_copy->AddEdgeCurve(crv_copy);
08345 dup = 0;
08346 }
08347 else
08348 c3_remap[i] = -1;
08349 }
08350 rc = ( rc && i == m_C3.Count() );
08351
08352
08353 for (i = 0; i < m_V.Count() && rc; i++ )
08354 {
08355 if (v_remap[i])
08356 {
08357 ON_BrepVertex& vertex_copy = brep_copy->NewVertex(m_V[i].point);
08358 memset(&vertex_copy.m_vertex_user,0,sizeof(vertex_copy.m_vertex_user));
08359 vertex_copy.m_vertex_user.i = i;
08360 v_remap[i] = vertex_copy.m_vertex_index;
08361 }
08362 else
08363 v_remap[i] = -1;
08364 }
08365 rc = ( rc && i == m_V.Count() );
08366
08367
08368 for (i = 0; i < m_E.Count() && rc; i++ )
08369 {
08370 if (e_remap[i])
08371 {
08372 const ON_BrepEdge& edge = m_E[i];
08373
08374 if ( edge.m_vi[0] < 0 || edge.m_vi[1] < 0 || edge.m_c3i < 0 )
08375 break;
08376 if ( v_remap[edge.m_vi[0]] < 0 || v_remap[edge.m_vi[1]] < 0 || c3_remap[edge.m_c3i] < 0)
08377 break;
08378 ON_BrepEdge& edge_copy = brep_copy->NewEdge( brep_copy->m_V[v_remap[edge.m_vi[0]]],
08379 brep_copy->m_V[v_remap[edge.m_vi[1]]],
08380 c3_remap[edge.m_c3i]
08381 );
08382 edge_copy.SetProxyCurveDomain( edge.ProxyCurveDomain());
08383 if ( edge.ProxyCurveIsReversed() )
08384 edge_copy.ON_CurveProxy::Reverse();
08385 edge_copy.SetDomain(edge.Domain());
08386
08387 memset(&edge_copy.m_edge_user,0,sizeof(edge_copy.m_edge_user));
08388 edge_copy.m_edge_user.i = i;
08389 edge_copy.m_tolerance = edge.m_tolerance;
08390 e_remap[i] = edge_copy.m_edge_index;
08391 }
08392 else
08393 e_remap[i] = -1;
08394 }
08395 rc = ( rc && i == m_E.Count() );
08396
08397
08398
08399
08400 bool bFoundBadIdx = false;
08401
08402
08403 for ( fi = 0; rc && fi < m_F.Count() && rc && !bFoundBadIdx; fi++ )
08404 {
08405 if ( f_remap[fi] == 0 )
08406 continue;
08407 rc = false;
08408 const ON_BrepFace& face = m_F[fi];
08409
08410
08411 si = (face.m_si>=0) ? s_remap[face.m_si] : -1;
08412 if ( si < 0 )
08413 break;
08414
08415 ON_BrepFace& face_copy = brep_copy->NewFace(si);
08416 memset(&face_copy.m_face_user,0,sizeof(face_copy.m_face_user));
08417 face_copy.m_face_user.i = fi;
08418 face_copy.m_bRev = face.m_bRev;
08419 face_copy.m_bbox = face.m_bbox;
08420 face_copy.m_domain[0] = face.m_domain[0];
08421 face_copy.m_domain[1] = face.m_domain[1];
08422
08423
08424
08425
08426 for ( fli = 0; fli < face.m_li.Count() && !bFoundBadIdx; fli++ )
08427 {
08428 li = face.m_li[fli];
08429 if (0 > li || m_L.Count() <= li)
08430 {
08431 bFoundBadIdx = true;
08432 break;
08433 }
08434
08435 const ON_BrepLoop& loop = m_L[li];
08436 ON_BrepLoop& loop_copy = brep_copy->NewLoop( loop.m_type, face_copy );
08437 memset(&loop_copy.m_loop_user,0,sizeof(loop_copy.m_loop_user));
08438 loop_copy.m_loop_user.i = li;
08439 for ( lti = 0; lti < loop.m_ti.Count() && !bFoundBadIdx; lti++ )
08440 {
08441 ti = loop.m_ti[lti];
08442 if (0 > ti || m_T.Count() <= ti)
08443 {
08444 bFoundBadIdx = true;
08445 break;
08446 }
08447 const ON_BrepTrim& trim = m_T[ti];
08448 i = (trim.m_c2i>=0) ? c2_remap[trim.m_c2i] : -1;
08449 if ( trim.m_ei >= 0 ) {
08450 i = brep_copy->NewTrim( brep_copy->m_E[e_remap[trim.m_ei]], trim.m_bRev3d, loop_copy, i ).m_trim_index;
08451 }
08452 else {
08453 i = brep_copy->NewTrim( trim.m_bRev3d, loop_copy, i ).m_trim_index;
08454 int vi0 = (trim.m_vi[0]>=0) ? v_remap[trim.m_vi[0]] : -1;
08455 int vi1 = (trim.m_vi[1]>=0) ? v_remap[trim.m_vi[1]] : -1;
08456 brep_copy->m_T[i].m_vi[0] = vi0;
08457 brep_copy->m_T[i].m_vi[1] = vi1;
08458 }
08459 ON_BrepTrim& trim_copy = brep_copy->m_T[i];
08460
08461
08462 trim_copy.SetProxyCurveDomain( trim.ProxyCurveDomain());
08463 if ( trim.ProxyCurveIsReversed() )
08464 trim_copy.ON_CurveProxy::Reverse();
08465 trim_copy.SetDomain(trim.Domain());
08466
08467 memset(&trim_copy.m_trim_user,0,sizeof(trim_copy.m_trim_user));
08468 trim_copy.m_trim_user.i = ti;
08469 trim_copy.m_iso = trim.m_iso;
08470 trim_copy.m_tolerance[0] = trim.m_tolerance[0];
08471 trim_copy.m_tolerance[1] = trim.m_tolerance[1];
08472 trim_copy.m_pline = trim.m_pline;
08473 trim_copy.m_pbox = trim.m_pbox;
08474 trim_copy.m__legacy_2d_tol = trim.m__legacy_2d_tol;
08475 trim_copy.m__legacy_3d_tol = trim.m__legacy_3d_tol;
08476 trim_copy.m__legacy_flags = trim.m__legacy_flags;
08477 }
08478
08479 if (bFoundBadIdx)
08480 break;
08481
08482 loop_copy.m_pbox = loop.m_pbox;
08483 }
08484
08485 if (bFoundBadIdx)
08486 break;
08487
08488 if ( bDuplicateMeshes )
08489 {
08490 if ( face.m_render_mesh )
08491 face_copy.m_render_mesh = face.m_render_mesh->Duplicate();
08492 if ( face.m_analysis_mesh )
08493 face_copy.m_analysis_mesh = face.m_analysis_mesh->Duplicate();
08494 if ( face.m_preview_mesh )
08495 face_copy.m_preview_mesh = face.m_preview_mesh->Duplicate();
08496 }
08497
08498 rc = true;
08499 }
08500 rc = ( rc && fi == m_F.Count() );
08501
08502 if ( !rc ) {
08503 if ( dup ) {
08504 delete dup;
08505 dup = 0;
08506 }
08507 if ( brep_copy ) {
08508 delete brep_copy;
08509 brep_copy = 0;
08510 }
08511 }
08512 else
08513 {
08514
08515 brep_copy->SetTrimTypeFlags();
08516 brep_copy->SetVertexTolerances();
08517 }
08518 return brep_copy;
08519 }
08520
08521 ON_Brep* ON_Brep::ExtractFace( int face_index )
08522 {
08523 ON_Brep* brep_copy = DuplicateFace(face_index,false);
08524 if ( brep_copy ) {
08525 ON_BrepFace& face = m_F[face_index];
08526 ON_BrepFace& face_copy = brep_copy->m_F[0];
08527 face_copy.m_render_mesh = face.m_render_mesh; face.m_render_mesh = 0;
08528 face_copy.m_analysis_mesh = face.m_analysis_mesh; face.m_analysis_mesh = 0;
08529 face_copy.m_preview_mesh = face.m_preview_mesh; face.m_preview_mesh = 0;
08530 DeleteFace( face, true );
08531 }
08532 return brep_copy;
08533 }
08534
08535 void ON_Brep::DeleteSurface(int si)
08536 {
08537 if ( si >= 0 && si < m_S.Count() ) {
08538 delete m_S[si];
08539 m_S[si] = 0;
08540 }
08541 }
08542
08543 void ON_Brep::Delete2dCurve(int c2i)
08544 {
08545 if ( c2i >= 0 && c2i < m_C2.Count() ) {
08546 delete m_C2[c2i];
08547 m_C2[c2i] = 0;
08548 }
08549 }
08550
08551 void ON_Brep::Delete3dCurve(int c3i)
08552 {
08553 if ( c3i >= 0 && c3i < m_C3.Count() ) {
08554 delete m_C3[c3i];
08555 m_C3[c3i] = 0;
08556 }
08557 }
08558
08559
08560 bool ON_Brep::CullUnusedFaces()
08561 {
08562 bool rc = true;
08563 int fcount = m_F.Count();
08564 if (fcount > 0 ) {
08565 ON_Workspace ws;
08566 int *fmap = ws.GetIntMemory(fcount+1);
08567 *fmap++ = -1;
08568 memset( fmap, 0, fcount*sizeof(*fmap) );
08569 const int lcount = m_L.Count();
08570 int fi, li, mi = 0;
08571
08572
08573 for ( fi = 0; fi < fcount; fi++ ) {
08574 ON_BrepFace& face = m_F[fi];
08575 if ( face.m_face_index == -1)
08576 fmap[fi] = -1;
08577 else if ( face.m_face_index == fi )
08578 fmap[fi] = face.m_face_index = mi++;
08579 else {
08580 ON_ERROR("Brep face has illegal m_face_index.");
08581 rc = false;
08582 fmap[fi] = face.m_face_index;
08583 }
08584 }
08585
08586 if ( mi == 0 ) {
08587 m_F.Destroy();
08588 }
08589 else if ( mi < fcount ) {
08590
08591 mi = 0;
08592 for ( fi = fcount-1; fi >= 0; fi-- ) {
08593 if ( m_F[fi].m_face_index == -1 )
08594 m_F.Remove(fi);
08595 else
08596 m_F[fi].m_face_index = fmap[fi];
08597 }
08598
08599
08600 for ( li = 0; li < lcount; li++ ) {
08601 ON_BrepLoop& loop = m_L[li];
08602 fi = loop.m_fi;
08603 if ( fi < -1 || fi >= fcount ) {
08604 ON_ERROR("Brep loop has illegal m_fi.");
08605 rc = false;
08606 }
08607 else
08608 loop.m_fi = fmap[fi];
08609 }
08610
08611 }
08612 }
08613 m_F.Shrink();
08614 return rc;
08615 }
08616
08617 bool ON_Brep::CullUnusedSurfaces()
08618 {
08619
08620 bool rc = true;
08621 const int fcount = m_F.Count();
08622 int scount = m_S.Count();
08623 int si, fi, mi;
08624
08625 if ( scount > 0 ) {
08626 ON_Workspace ws;
08627 int* smap = ws.GetIntMemory(scount+1);
08628 *smap++ = -1;
08629 memset(smap,0,scount*sizeof(*smap));
08630 mi = 0;
08631 for ( fi = 0; fi < fcount; fi++ ) {
08632 ON_BrepFace& face = m_F[fi];
08633 if ( face.m_face_index == -1 ) {
08634 face.m_si = -1;
08635 continue;
08636 }
08637 si = face.m_si;
08638 if ( si == -1 )
08639 continue;
08640 if ( si < 0 || si >= scount ) {
08641 ON_ERROR("Brep face has illegal m_si.");
08642 rc = false;
08643 }
08644 else {
08645 if ( !smap[si] )
08646 mi++;
08647 smap[si]++;
08648 }
08649 }
08650
08651 if ( mi == 0 ) {
08652 m_S.Destroy();
08653 }
08654 else if ( mi < scount ) {
08655 mi = 0;
08656 for ( si = 0; si < scount; si++ ) {
08657 if ( smap[si] )
08658 smap[si] = mi++;
08659 else {
08660 delete m_S[si];
08661 m_S[si] = 0;
08662 smap[si] = -1;
08663 }
08664 }
08665
08666 for ( fi = 0; fi < fcount; fi++ ) {
08667 ON_BrepFace& face = m_F[fi];
08668 si = face.m_si;
08669 if ( si >= 0 && si < scount )
08670 face.m_si = smap[si];
08671 }
08672
08673 for ( si = scount-1; si >= 0; si-- ) {
08674 if ( smap[si] < 0 ) {
08675 m_S.Remove(si);
08676 scount--;
08677 }
08678 }
08679 }
08680 }
08681 m_S.Shrink();
08682 return rc;
08683 }
08684
08685 bool ON_Brep::CullUnused3dCurves()
08686 {
08687
08688 bool rc = true;
08689 const int ecount = m_E.Count();
08690 int c3count = m_C3.Count();
08691 int c3i, ei, mi;
08692
08693 if ( c3count > 0 ) {
08694 ON_Workspace ws;
08695 int* c3map = ws.GetIntMemory(c3count+1);
08696 *c3map++ = -1;
08697 memset(c3map,0,c3count*sizeof(*c3map));
08698 mi = 0;
08699 for ( ei = 0; ei < ecount; ei++ ) {
08700 ON_BrepEdge& edge = m_E[ei];
08701 if ( edge.m_edge_index == -1 ) {
08702 edge.m_c3i = -1;
08703 continue;
08704 }
08705 c3i = edge.m_c3i;
08706 if ( c3i == -1 )
08707 continue;
08708 if ( c3i < -1 || c3i >= c3count ) {
08709 ON_ERROR("Brep edge has illegal m_c3i.");
08710 rc = false;
08711 }
08712 else {
08713 if ( !c3map[c3i] )
08714 mi++;
08715 c3map[c3i]++;
08716 }
08717 }
08718
08719 if ( mi == 0 ) {
08720 m_C3.Destroy();
08721 }
08722 else if ( mi < c3count ) {
08723 mi = 0;
08724 for ( c3i = 0; c3i < c3count; c3i++ ) {
08725 if ( c3map[c3i] )
08726 c3map[c3i] = mi++;
08727 else {
08728 delete m_C3[c3i];
08729 m_C3[c3i] = 0;
08730 c3map[c3i] = -1;
08731 }
08732 }
08733
08734 for ( ei = 0; ei < ecount; ei++ ) {
08735 ON_BrepEdge& edge = m_E[ei];
08736 c3i = edge.m_c3i;
08737 if ( c3i >= 0 && c3i < c3count )
08738 edge.m_c3i = c3map[c3i];
08739 }
08740
08741 for ( c3i = c3count-1; c3i >= 0; c3i-- ) {
08742 if ( c3map[c3i] < 0 ) {
08743 m_C3.Remove(c3i);
08744 c3count--;
08745 }
08746 }
08747 }
08748 }
08749 m_C3.Shrink();
08750 return rc;
08751 }
08752
08753
08754 bool ON_Brep::CullUnused2dCurves()
08755 {
08756
08757 bool rc = true;
08758 const int tcount = m_T.Count();
08759 int c2count = m_C2.Count();
08760 int c2i, ti, mi;
08761
08762 if ( c2count > 0 )
08763 {
08764 ON_Workspace ws;
08765 int* c2map = ws.GetIntMemory(c2count+1);
08766 *c2map++ = -1;
08767 memset(c2map,0,c2count*sizeof(*c2map));
08768 mi = 0;
08769 for ( ti = 0; ti < tcount; ti++ ) {
08770 ON_BrepTrim& trim = m_T[ti];
08771 if ( trim.m_trim_index == -1 ) {
08772 trim.m_c2i = -1;
08773 continue;
08774 }
08775 c2i = trim.m_c2i;
08776 if ( c2i == -1 )
08777 continue;
08778 if ( c2i < -1 || c2i >= c2count ) {
08779 ON_ERROR("Brep trim has illegal m_c2i.");
08780 rc = false;
08781 }
08782 else {
08783 if ( !c2map[c2i] )
08784 mi++;
08785 c2map[c2i]++;
08786 }
08787 }
08788
08789 if ( mi == 0 ) {
08790 m_C2.Destroy();
08791 }
08792 else if ( mi < c2count ) {
08793 mi = 0;
08794 for ( c2i = 0; c2i < c2count; c2i++ ) {
08795 if ( c2map[c2i] )
08796 c2map[c2i] = mi++;
08797 else {
08798 delete m_C2[c2i];
08799 m_C2[c2i] = 0;
08800 c2map[c2i] = -1;
08801 }
08802 }
08803
08804 for ( ti = 0; ti < tcount; ti++ ) {
08805 ON_BrepTrim& trim = m_T[ti];
08806 c2i = trim.m_c2i;
08807 if ( c2i >= 0 && c2i < c2count )
08808 trim.m_c2i = c2map[c2i];
08809 }
08810
08811 for ( c2i = c2count-1; c2i >= 0; c2i-- ) {
08812 if ( c2map[c2i] < 0 ) {
08813 m_C2.Remove(c2i);
08814 c2count--;
08815 }
08816 }
08817 }
08818 }
08819 m_C2.Shrink();
08820 return rc;
08821 }
08822
08823
08824 bool ON_Brep::CullUnusedLoops()
08825 {
08826 bool rc = true;
08827 const int lcount = m_L.Count();
08828 if ( lcount > 0 ) {
08829 ON_Workspace ws;
08830 int* lmap = ws.GetIntMemory(lcount+1);
08831 *lmap++ = -1;
08832 memset( lmap, 0, lcount*sizeof(*lmap) );
08833 const int fcount = m_F.Count();
08834 const int tcount = m_T.Count();
08835 int li, fli, flcnt, fi, ti, mi;
08836
08837 mi = 0;
08838 for ( li = 0; li < lcount; li++ ) {
08839 ON_BrepLoop& loop = m_L[li];
08840 if ( loop.m_loop_index == -1)
08841 lmap[li] = -1;
08842 else if ( loop.m_loop_index == li )
08843 lmap[li] = loop.m_loop_index = mi++;
08844 else {
08845 ON_ERROR("Brep loop has illegal m_loop_index.");
08846 rc = false;
08847 lmap[li] = loop.m_loop_index;
08848 }
08849 }
08850
08851 if ( mi == 0 ) {
08852 m_L.Destroy();
08853 }
08854 else if ( mi < lcount ) {
08855
08856
08857 for ( li = lcount-1; li >= 0; li-- ) {
08858 if ( m_L[li].m_loop_index == -1 )
08859 m_L.Remove(li);
08860 else
08861 m_L[li].m_loop_index = lmap[li];
08862 }
08863
08864
08865 for ( fi = 0; fi < fcount; fi++ ) {
08866 ON_BrepFace& face = m_F[fi];
08867 flcnt = face.m_li.Count();
08868 for ( fli = flcnt-1; fli >= 0; fli-- ) {
08869 li = face.m_li[fli];
08870 if ( li < -1 || li >= lcount ) {
08871 ON_ERROR("Brep face m_li[] has illegal loop index.");
08872 rc = false;
08873 }
08874 else {
08875 li = lmap[li];
08876 if (li >= 0 ) {
08877 face.m_li[fli] = li;
08878 }
08879 else {
08880 face.m_li.Remove(fli);
08881 }
08882 }
08883 }
08884 }
08885
08886
08887 for ( ti = 0; ti < tcount; ti++ ) {
08888 ON_BrepTrim& trim = m_T[ti];
08889 li = trim.m_li;
08890 if ( li < -1 || li >= lcount ) {
08891 ON_ERROR("Brep trim has illegal m_li.");
08892 rc = false;
08893 }
08894 else {
08895 trim.m_li = lmap[li];
08896 }
08897 }
08898 }
08899 }
08900 m_L.Shrink();
08901 return rc;
08902 }
08903
08904 bool ON_Brep::CullUnusedTrims()
08905 {
08906 bool rc = true;
08907 const int tcount = m_T.Count();
08908 if ( tcount > 0 ) {
08909 ON_Workspace ws;
08910 int *tmap = ws.GetIntMemory(tcount+1);
08911 *tmap++ = -1;
08912 memset( tmap, 0, tcount*sizeof(*tmap));
08913 const int lcount = m_L.Count();
08914 const int ecount = m_E.Count();
08915 int ti, li, ei, mi, ltcnt, lti, etcnt, eti;
08916
08917 mi = 0;
08918 for ( ti = 0; ti < tcount; ti++ ) {
08919 ON_BrepTrim& trim = m_T[ti];
08920 if ( trim.m_trim_index == -1)
08921 tmap[ti] = -1;
08922 else if ( trim.m_trim_index == ti )
08923 tmap[ti] = trim.m_trim_index = mi++;
08924 else {
08925 ON_ERROR("Brep trim has illegal m_trim_index.");
08926 rc = false;
08927 tmap[ti] = trim.m_trim_index;
08928 }
08929 }
08930
08931 if ( mi == 0 ) {
08932 m_T.Destroy();
08933 }
08934 else if ( mi < tcount ) {
08935
08936 for ( ti = tcount-1; ti >= 0; ti-- ) {
08937 if ( m_T[ti].m_trim_index == -1 ) {
08938 m_T.Remove(ti);
08939 }
08940 else {
08941 m_T[ti].m_trim_index = tmap[ti];
08942 }
08943 }
08944
08945
08946 for ( li = 0; li < lcount; li++ ) {
08947 ON_BrepLoop& loop = m_L[li];
08948 ltcnt = loop.m_ti.Count();
08949 for ( lti = ltcnt-1; lti >= 0; lti-- ) {
08950 ti = loop.m_ti[lti];
08951 if ( ti < -1 || ti >= tcount ) {
08952 ON_ERROR("Brep loop.m_ti[] has illegal index.");
08953 rc = false;
08954 }
08955 else {
08956 ti = tmap[ti];
08957 if (ti >= 0 ) {
08958 loop.m_ti[lti] = ti;
08959 }
08960 else {
08961 loop.m_ti.Remove(lti);
08962 }
08963 }
08964 }
08965 }
08966
08967
08968 for ( ei = 0; ei < ecount; ei++ ) {
08969 ON_BrepEdge& edge = m_E[ei];
08970 etcnt = edge.m_ti.Count();
08971 for ( eti = etcnt-1; eti >= 0; eti-- ) {
08972 ti = edge.m_ti[eti];
08973 if ( ti < -1 || ti >= tcount ) {
08974 ON_ERROR("Brep edge.m_ti[] has illegal index.");
08975 rc = false;
08976 }
08977 else {
08978 ti = tmap[ti];
08979 if (ti >= 0 ) {
08980 edge.m_ti[eti] = ti;
08981 }
08982 else {
08983 edge.m_ti.Remove(eti);
08984 }
08985 }
08986 }
08987 }
08988 }
08989 }
08990 m_T.Shrink();
08991 return rc;
08992 }
08993
08994 bool ON_Brep::CullUnusedEdges()
08995 {
08996 bool rc = true;
08997 const int ecount = m_E.Count();
08998 if ( ecount > 0 ) {
08999 ON_Workspace ws;
09000 int* emap = ws.GetIntMemory(ecount+1);
09001 *emap++ = -1;
09002 memset( emap, 0, ecount*sizeof(*emap) );
09003 const int vcount = m_V.Count();
09004 const int tcount = m_T.Count();
09005 int ei, ti, vi, mi, vecnt, vei;
09006
09007 mi = 0;
09008 for ( ei = 0; ei < ecount; ei++ ) {
09009 ON_BrepEdge& edge = m_E[ei];
09010 if ( edge.m_edge_index == -1)
09011 emap[ei] = -1;
09012 else if ( edge.m_edge_index == ei )
09013 emap[ei] = edge.m_edge_index = mi++;
09014 else {
09015 ON_ERROR("Brep edge has illegal m_edge_index.");
09016 rc = false;
09017 emap[ei] = edge.m_edge_index;
09018 }
09019 }
09020
09021 if ( mi == 0 ) {
09022 m_E.Destroy();
09023 }
09024 else if ( mi < ecount )
09025 {
09026
09027 for ( ei = ecount-1; ei >= 0; ei-- ) {
09028 if ( m_E[ei].m_edge_index == -1 ) {
09029 m_E.Remove(ei);
09030 }
09031 else {
09032 m_E[ei].m_edge_index = emap[ei];
09033 }
09034 }
09035
09036
09037 for ( ti = 0; ti < tcount; ti++ ) {
09038 ON_BrepTrim& trim = m_T[ti];
09039 ei = trim.m_ei;
09040 if ( ei < -1 || ei >= ecount ) {
09041 ON_ERROR("Brep trim.m_ei has illegal index.");
09042 rc = false;
09043 }
09044 else {
09045 trim.m_ei = emap[ei];
09046 }
09047 }
09048
09049
09050 for ( vi = 0; vi < vcount; vi++ ) {
09051 ON_BrepVertex& vertex = m_V[vi];
09052 vecnt = vertex.m_ei.Count();
09053 for ( vei = vecnt-1; vei >= 0; vei-- ) {
09054 ei = vertex.m_ei[vei];
09055 if ( ei < -1 || ei >= ecount ) {
09056 ON_ERROR("Brep vertex.m_ei[] has illegal index.");
09057 rc = false;
09058 }
09059 else {
09060 ei = emap[ei];
09061 if (ei >= 0 ) {
09062 vertex.m_ei[vei] = ei;
09063 }
09064 else {
09065 vertex.m_ei.Remove(vei);
09066 }
09067 }
09068 }
09069 }
09070 }
09071 }
09072 m_E.Shrink();
09073 return rc;
09074 }
09075
09076
09077 bool ON_Brep::CullUnusedVertices()
09078 {
09079 bool rc = true;
09080 const int vcount = m_V.Count();
09081 if ( vcount > 0 )
09082 {
09083 ON_Workspace ws;
09084 int* vmap = ws.GetIntMemory(vcount+1);
09085 *vmap++ = -1;
09086 memset(vmap,0,vcount*sizeof(*vmap));
09087 const int tcount = m_T.Count();
09088 const int ecount = m_E.Count();
09089 int vi, ei, ti, mi, j;
09090
09091 if ( tcount > 0 )
09092 {
09093
09094
09095 for ( ti = 0; ti < tcount; ti++ )
09096 {
09097 const ON_BrepTrim& trim = m_T[ti];
09098 if ( -1 == trim.m_trim_index )
09099 continue;
09100 vi = trim.m_vi[0];
09101 if ( vi >= 0 && vi < vcount && -1 == m_V[vi].m_vertex_index )
09102 {
09103
09104
09105
09106
09107 ON_ERROR("ON_Brep::CullUnusedVertices() - deleted vertex referenced by trim.m_vi[0]");
09108 m_V[vi].m_vertex_index = vi;
09109 }
09110 vi = trim.m_vi[1];
09111 if ( vi >= 0 && vi < vcount && -1 == m_V[vi].m_vertex_index )
09112 {
09113
09114
09115
09116
09117 ON_ERROR("ON_Brep::CullUnusedVertices() - deleted vertex referenced by trim.m_vi[1]");
09118 m_V[vi].m_vertex_index = vi;
09119 }
09120 }
09121 }
09122
09123 mi = 0;
09124 for ( vi = 0; vi < vcount; vi++ ) {
09125 ON_BrepVertex& vertex = m_V[vi];
09126 if ( vertex.m_vertex_index == -1)
09127 vmap[vi] = -1;
09128 else if ( vertex.m_vertex_index == vi )
09129 vmap[vi] = vertex.m_vertex_index = mi++;
09130 else {
09131 ON_ERROR("Brep vertex has illegal m_vertex_index.");
09132 rc = false;
09133 vmap[vi] = vertex.m_vertex_index;
09134 }
09135 }
09136
09137 if ( mi == 0 )
09138 {
09139 m_V.Destroy();
09140 }
09141 else if ( mi < vcount )
09142 {
09143
09144 for ( vi = vcount-1; vi >= 0; vi-- )
09145 {
09146 if ( m_V[vi].m_vertex_index == -1 )
09147 {
09148 m_V.Remove(vi);
09149 }
09150 else {
09151 m_V[vi].m_vertex_index = vmap[vi];
09152 }
09153 }
09154
09155
09156 for ( ei = 0; ei < ecount; ei++ )
09157 {
09158 ON_BrepEdge& edge = m_E[ei];
09159 for ( j = 0; j < 2; j++ )
09160 {
09161 vi = edge.m_vi[j];
09162 if ( vi < -1 || vi >= vcount )
09163 {
09164 ON_ERROR("Brep edge.m_vi[] has illegal index.");
09165 rc = false;
09166 }
09167 else {
09168 edge.m_vi[j] = vmap[vi];
09169 }
09170 }
09171 }
09172
09173
09174 for ( ti = 0; ti < tcount; ti++ )
09175 {
09176 ON_BrepTrim& trim = m_T[ti];
09177 for ( j = 0; j < 2; j++ )
09178 {
09179 vi = trim.m_vi[j];
09180 if ( vi < -1 || vi >= vcount )
09181 {
09182 ON_ERROR("Brep trim.m_vi[] has illegal index.");
09183 rc = false;
09184 }
09185 else {
09186 trim.m_vi[j] = vmap[vi];
09187 }
09188 }
09189 }
09190
09191 }
09192 }
09193 m_V.Shrink();
09194 return rc;
09195 }
09196
09197 bool ON_Brep::Compact()
09198 {
09199
09200
09201
09202
09203 bool rc = true;
09204 if (!CullUnusedFaces())
09205 rc = false;
09206 if (!CullUnusedEdges())
09207 rc = false;
09208 if (!CullUnusedVertices())
09209 rc = false;
09210 if (!CullUnusedLoops())
09211 rc = false;
09212 if (!CullUnusedTrims())
09213 rc = false;
09214
09215 if (!CullUnusedSurfaces())
09216 rc = false;
09217 if (!CullUnused3dCurves())
09218 rc = false;
09219 if (!CullUnused2dCurves())
09220 rc = false;
09221
09222
09223
09224
09225
09226 ON_SimpleArray<bool> used;
09227 bool bSyncUp;
09228
09229 if ( m_C2.Count() == m_T.Count() )
09230 {
09231 int i, count = m_C2.Count();
09232 used.Reserve(count);
09233 used.SetCount(count);
09234 used.Zero();
09235 bSyncUp = true;
09236 for ( i = 0; i < count && bSyncUp; i++ )
09237 {
09238 const ON_BrepTrim& trim = m_T[i];
09239 if ( trim.m_trim_index != i || trim.m_c2i < 0 || trim.m_c2i >= count )
09240 bSyncUp = false;
09241 else
09242 {
09243 if (used[trim.m_c2i])
09244 bSyncUp = false;
09245 else
09246 used[trim.m_c2i] = true;
09247 }
09248 }
09249 if ( bSyncUp )
09250 {
09251 ON_SimpleArray< ON_Curve* > ptr(count);
09252 for( i = 0; i < count; i++ )
09253 {
09254 ON_BrepTrim& trim = m_T[i];
09255 ptr[i] = m_C2[trim.m_c2i];
09256 trim.m_c2i = i;
09257 }
09258 for( i = 0; i < count; i++ )
09259 {
09260 m_C2[i] = ptr[i];
09261 }
09262 }
09263 }
09264
09265 if ( m_C3.Count() == m_E.Count() )
09266 {
09267 int i, count = m_C3.Count();
09268 used.Reserve(count);
09269 used.SetCount(count);
09270 used.Zero();
09271 bSyncUp = true;
09272 for ( i = 0; i < count && bSyncUp; i++ )
09273 {
09274 const ON_BrepEdge& edge = m_E[i];
09275 if ( edge.m_edge_index != i || edge.m_c3i < 0 || edge.m_c3i >= count )
09276 bSyncUp = false;
09277 else
09278 {
09279 if (used[edge.m_c3i])
09280 bSyncUp = false;
09281 else
09282 used[edge.m_c3i] = true;
09283 }
09284 }
09285 if ( bSyncUp )
09286 {
09287 ON_SimpleArray< ON_Curve* > ptr(count);
09288 for( i = 0; i < count; i++ )
09289 {
09290 ON_BrepEdge& edge = m_E[i];
09291 ptr[i] = m_C3[edge.m_c3i];
09292 edge.m_c3i = i;
09293 }
09294 for( i = 0; i < count; i++ )
09295 {
09296 m_C3[i] = ptr[i];
09297 }
09298 }
09299 }
09300
09301 if ( m_S.Count() == m_F.Count() )
09302 {
09303 int i, count = m_S.Count();
09304 used.Reserve(count);
09305 used.SetCount(count);
09306 used.Zero();
09307 bSyncUp = true;
09308 for ( i = 0; i < count && bSyncUp; i++ )
09309 {
09310 const ON_BrepFace& face = m_F[i];
09311 if ( face.m_face_index != i || face.m_si < 0 || face.m_si >= count )
09312 bSyncUp = false;
09313 else
09314 {
09315 if (used[face.m_si])
09316 bSyncUp = false;
09317 else
09318 used[face.m_si] = true;
09319 }
09320 }
09321 if ( bSyncUp )
09322 {
09323 ON_SimpleArray< ON_Surface* > ptr(count);
09324 for( i = 0; i < count; i++ )
09325 {
09326 ON_BrepFace& face = m_F[i];
09327 ptr[i] = m_S[face.m_si];
09328 face.m_si = i;
09329 }
09330 for( i = 0; i < count; i++ )
09331 {
09332 m_S[i] = ptr[i];
09333 }
09334 }
09335 }
09336
09337 return rc;
09338 }
09339
09340
09341 ON_Brep& ON_Brep::operator=(const ON_Brep& src)
09342 {
09343 if ( this != &src )
09344 {
09345 Destroy();
09346 ON_Geometry::operator=(src);
09347
09348 m_V.SetCapacity(src.m_V.Count());
09349 m_E.SetCapacity(src.m_E.Count());
09350 m_F.SetCapacity(src.m_F.Count());
09351 m_T.SetCapacity(src.m_T.Count());
09352 m_L.SetCapacity(src.m_L.Count());
09353
09354 m_V.SetCount(src.m_V.Count());
09355 m_E.SetCount(src.m_E.Count());
09356 m_F.SetCount(src.m_F.Count());
09357 m_T.SetCount(src.m_T.Count());
09358 m_L.SetCount(src.m_L.Count());
09359
09360 src.m_C2.Duplicate( m_C2 );
09361 src.m_C3.Duplicate( m_C3 );
09362 src.m_S.Duplicate( m_S );
09363
09364 int i, count = m_V.Count();
09365 for ( i = 0; i < count; i++ )
09366 {
09367 m_V[i] = src.m_V[i];
09368 }
09369
09370 count = m_E.Count();
09371 for ( i = 0; i < count; i++ )
09372 {
09373 m_E[i] = src.m_E[i];
09374 ON_BrepEdge& e = m_E[i];
09375 e.m_brep = this;
09376
09377
09378 e.SetProxyCurve( ( e.m_c3i >= 0 ) ? m_C3[e.m_c3i] : 0,
09379 src.m_E[i].ProxyCurveDomain()
09380 );
09381 if ( src.m_E[i].ProxyCurveIsReversed() )
09382 e.ON_CurveProxy::Reverse();
09383 e.SetDomain( src.m_E[i].Domain() );
09384 }
09385
09386 count = m_L.Count();
09387 for ( i = 0; i < count; i++ )
09388 {
09389 m_L[i].m_brep = this;
09390 }
09391
09392 count = m_F.Count();
09393 for ( i = 0; i < count; i++ )
09394 {
09395 m_F[i] = src.m_F[i];
09396 ON_BrepFace& f = m_F[i];
09397 f.m_brep = this;
09398
09399 f.SetProxySurface(( f.m_si >= 0 ) ? m_S[f.m_si] : 0);
09400 f.m_bbox = src.m_F[i].m_bbox;
09401 }
09402
09403 count = m_T.Count();
09404 for ( i = 0; i < count; i++ )
09405 {
09406 m_T[i] = src.m_T[i];
09407 ON_BrepTrim& trim = m_T[i];
09408 trim.m_brep = this;
09409
09410
09411 trim.SetProxyCurve( ( trim.m_c2i >= 0 ) ? m_C2[trim.m_c2i] : 0,
09412 src.m_T[i].ProxyCurveDomain()
09413 );
09414 if ( src.m_T[i].ProxyCurveIsReversed() )
09415 trim.ON_CurveProxy::Reverse();
09416 trim.SetDomain( src.m_T[i].Domain() );
09417 }
09418
09419 count = m_L.Count();
09420 for ( i = 0; i < count; i++ )
09421 {
09422 m_L[i] = src.m_L[i];
09423 }
09424
09425 m_bbox = src.m_bbox;
09426 m_is_solid = src.m_is_solid;
09427 }
09428 return *this;
09429 }
09430
09431 void ON_Brep::Destroy()
09432 {
09433 m_V.Empty();
09434 m_E.Empty();
09435 m_F.Empty();
09436 m_T.Empty();
09437 m_L.Empty();
09438
09439 int i, count = m_C2.Count();
09440 for ( i = 0; i < count; i++ ) {
09441 delete m_C2[i];
09442 m_C2[i] = 0;
09443 }
09444 m_C2.Empty();
09445 m_C2.Zero();
09446
09447 count = m_C3.Count();
09448 for ( i = 0; i < count; i++ ) {
09449 delete m_C3[i];
09450 m_C3[i] = 0;
09451 }
09452 m_C3.Empty();
09453 m_C3.Zero();
09454
09455 count = m_S.Count();
09456 for ( i = 0; i < count; i++ ) {
09457 delete m_S[i];
09458 m_S[i] = 0;
09459 }
09460 m_S.Empty();
09461 m_S.Zero();
09462
09463 m_bbox.Destroy();
09464 m_is_solid = 0;
09465
09466 }
09467
09468 void ON_Brep::EmergencyDestroy()
09469 {
09470
09471
09472 m_V.EmergencyDestroy();
09473 m_E.EmergencyDestroy();
09474 m_F.EmergencyDestroy();
09475 m_T.EmergencyDestroy();
09476 m_L.EmergencyDestroy();
09477 m_C2.EmergencyDestroy();
09478 m_C3.EmergencyDestroy();
09479 m_S.EmergencyDestroy();
09480 m_bbox.Destroy();
09481 m_is_solid = 0;
09482 }
09483
09484 bool ON_Brep::CombineCoincidentVertices(ON_BrepVertex& vertex0, ON_BrepVertex& vertex1)
09485 {
09486
09487 bool rc = false;
09488 if (&vertex0 == &vertex1) {
09489 ON_ERROR("ON_Brep::CombineCoincidentVertices - vertex0 = vertex1.");
09490 return rc;
09491 }
09492
09493 int runaway, vei, vecnt, ei, eti, etcnt, ti, prev_ti, next_ti;
09494
09495 if ( vertex0.m_vertex_index >= 0 && vertex1.m_vertex_index != vertex0.m_vertex_index ) {
09496 rc = true;
09497
09498 vecnt = vertex1.m_ei.Count();
09499 for ( vei = 0; vei < vecnt; vei++ ) {
09500 ei = vertex1.m_ei[vei];
09501 if ( ei >= 0 ) {
09502
09503 ON_BrepEdge& edge = m_E[ei];
09504 if ( edge.m_vi[0] == vertex1.m_vertex_index )
09505 edge.m_vi[0] = vertex0.m_vertex_index;
09506 if ( edge.m_vi[1] == vertex1.m_vertex_index )
09507 edge.m_vi[1] = vertex0.m_vertex_index;
09508
09509
09510 etcnt = edge.m_ti.Count();
09511 for (eti = 0; eti < etcnt; eti++ ) {
09512 ti = edge.m_ti[eti];
09513 if (ti >= 0 ) {
09514 ON_BrepTrim& trim = m_T[ti];
09515 if ( trim.m_vi[0] == vertex1.m_vertex_index ) {
09516 trim.m_vi[0] = vertex0.m_vertex_index;
09517
09518 for (prev_ti = PrevTrim(ti), runaway=0;prev_ti >= 0 && prev_ti != ti && runaway < 1024;prev_ti=PrevTrim(prev_ti),runaway++) {
09519 ON_BrepTrim& prevtrim = m_T[prev_ti];
09520 if ( prevtrim.m_ei >= 0 )
09521 break;
09522 if ( prevtrim.m_vi[0] == vertex1.m_vertex_index )
09523 prevtrim.m_vi[0] = vertex0.m_vertex_index;
09524 if ( prevtrim.m_vi[1] == vertex1.m_vertex_index )
09525 prevtrim.m_vi[1] = vertex0.m_vertex_index;
09526 }
09527 }
09528 if ( trim.m_vi[1] == vertex1.m_vertex_index ) {
09529 trim.m_vi[1] = vertex0.m_vertex_index;
09530
09531 for (next_ti = NextTrim(ti), runaway=0;next_ti >= 0 && next_ti != ti && runaway < 1024;next_ti=NextTrim(next_ti),runaway++) {
09532 ON_BrepTrim& nexttrim = m_T[next_ti];
09533 if ( nexttrim.m_ei >= 0 )
09534 break;
09535 if ( nexttrim.m_vi[0] == vertex1.m_vertex_index )
09536 nexttrim.m_vi[0] = vertex0.m_vertex_index;
09537 if ( nexttrim.m_vi[1] == vertex1.m_vertex_index )
09538 nexttrim.m_vi[1] = vertex0.m_vertex_index;
09539 }
09540 }
09541 }
09542 }
09543 vertex0.m_ei.Append(ei);
09544 }
09545 }
09546 }
09547
09548
09549 if ( vertex0.m_tolerance != ON_UNSET_VALUE)
09550 SetVertexTolerance(vertex0);
09551
09552 vertex1.m_vertex_index = -1;
09553 vertex1.m_ei.Destroy();
09554 DeleteVertex(vertex1);
09555
09556 return rc;
09557 }
09558
09559
09560 ON_BrepEdge* ON_Brep::CombineContiguousEdges(
09561 int ei0,
09562 int ei1,
09563 double angle_tolerance_radians
09564 )
09565 {
09566
09567
09568
09569
09570
09571
09572
09573
09574 const ON_BrepEdge* edge0 = Edge(ei0);
09575 const ON_BrepEdge* edge1 = Edge(ei1);
09576 if ( !edge0 || !edge1 )
09577 return 0;
09578
09579
09580 ei0 = edge0->m_edge_index;
09581 ei1 = edge1->m_edge_index;
09582 if ( ei0 < 0 || ei1 < 0 || ei0 == ei1 )
09583 return 0;
09584
09585
09586 if ( edge0->m_ti.Count() != edge1->m_ti.Count() )
09587 return 0;
09588
09589
09590
09591
09592 int end0 = 1, end1 = 0;
09593 bool MatchFound = false;
09594 for(end0=1; !MatchFound && end0>=0; ){
09595 int vi = edge0->m_vi[end0];
09596 const ON_BrepVertex* v = Vertex(vi);
09597 if(v && v->m_ei.Count()==2 ){
09598 for(end1=0; !MatchFound && end1<2; ){
09599 MatchFound = (vi == edge1->m_vi[end1]);
09600 if(!MatchFound)
09601 end1++;
09602 }
09603 }
09604 if(!MatchFound)
09605 end0--;
09606 }
09607 if(!MatchFound)
09608 return 0;
09609
09610
09611 const int vi_mid = edge0->m_vi[end0];
09612 {
09613 const ON_BrepVertex* v = Vertex(vi_mid);
09614 if ( !v )
09615 return 0;
09616 if ( v->m_ei.Count() != 2 )
09617 return 0;
09618 if ( v->m_ei[0] != ei0 && v->m_ei[1] != ei0 )
09619 return 0;
09620 if ( v->m_ei[0] != ei1 && v->m_ei[1] != ei1 )
09621 return 0;
09622 }
09623
09624
09625 const int evi0 = edge0->m_vi[1-end0];
09626
09627
09628 const int evi1 = edge1->m_vi[1-end1];
09629 if ( evi0 == vi_mid )
09630 return 0;
09631 if ( evi1 == vi_mid )
09632 return 0;
09633
09634
09635 const int vi0 = (end0==1) ? evi0 : evi1;
09636 const int vi1 = (end0==1) ? evi1 : evi0;
09637
09638
09639 {
09640 ON_3dVector tan0 = edge0->TangentAt( edge0->Domain()[end0] );
09641 if ( end0 == 0 )
09642 tan0.Reverse();
09643 ON_3dVector tan1 = edge1->TangentAt( edge1->Domain()[end1] );
09644 if ( end1 == 1 )
09645 tan1.Reverse();
09646 double d = tan0*tan1;
09647 if ( d < cos(angle_tolerance_radians) )
09648 return 0;
09649 }
09650
09651
09652 int trim_count = edge0->m_ti.Count();
09653 ON_SimpleArray<int> trim0_index(trim_count);
09654 ON_SimpleArray<int> trim1_index(trim_count);
09655 ON_SimpleArray<int> loop_lti0(trim_count);
09656 ON_SimpleArray<int> loop_lti1(trim_count);
09657
09658 int eti;
09659 for ( eti = 0; eti < trim_count; eti++ )
09660 {
09661 const ON_BrepTrim* trim0 = Trim( edge0->m_ti[eti] );
09662 if ( !trim0 )
09663 return 0;
09664 int ti0 = trim0->m_trim_index;
09665 const ON_BrepLoop* loop = trim0->Loop();
09666 if ( !loop )
09667 return 0;
09668 if ( loop->m_ti.Count() < 2 )
09669 return 0;
09670
09671
09672 bool bRev = (end0==0);
09673 if ( trim0->m_bRev3d )
09674 bRev = !bRev;
09675 int lti1 = -1;
09676 int lti0 = loop->m_ti.Search( &ti0, ON_CompareIncreasing<int> );
09677 if ( lti0 < 0 )
09678 return 0;
09679 if ( bRev )
09680 lti1 = lti0 - 1 + loop->m_ti.Count();
09681 else
09682 lti1 = lti0 +1;
09683 lti1 %= loop->m_ti.Count();
09684 const ON_BrepTrim* trim1 = loop->Trim(lti1);
09685 if ( !trim1 )
09686 return 0;
09687 if ( trim1->m_ei != ei1 )
09688 return 0;
09689 if ( trim0->m_trim_index == trim1->m_trim_index )
09690 return 0;
09691
09692
09693 int tend0 = trim0->m_bRev3d ? (1-end0) : end0;
09694 int tend1 = trim1->m_bRev3d ? (1-end1) : end1;
09695 if ( tend0 == tend1 )
09696 return 0;
09697 if ( trim0->m_vi[tend0] != vi_mid )
09698 return 0;
09699 if ( trim1->m_vi[tend1] != vi_mid )
09700 return 0;
09701 if ( trim0->m_vi[1-tend0] != evi0 )
09702 return 0;
09703 if ( trim1->m_vi[1-tend1] != evi1 )
09704 return 0;
09705 trim0_index.Append(trim0->m_trim_index);
09706 trim1_index.Append(trim1->m_trim_index);
09707 loop_lti0.Append(lti0);
09708 loop_lti1.Append(lti1);
09709 }
09710
09711
09712
09713 ON_PolyCurve* ec = 0;
09714 {
09715 ON_Curve* ec0 = edge0->DuplicateCurve();
09716 if ( !ec0 )
09717 return 0;
09718 ON_Curve* ec1 = edge1->DuplicateCurve();
09719 if ( !ec1 )
09720 {
09721 delete ec0;
09722 return 0;
09723 }
09724 if ( end0 == end1 )
09725 {
09726 if ( !ec1->Reverse() )
09727 {
09728 delete ec0;
09729 delete ec1;
09730 return 0;
09731 }
09732 }
09733 ec = new ON_PolyCurve();
09734 if ( end0 == 1 )
09735 {
09736 ec->Append(ec0);
09737 ec->AppendAndMatch(ec1);
09738 }
09739 else
09740 {
09741 ec->Append(ec1);
09742 ec->AppendAndMatch(ec0);
09743 }
09744 ec->RemoveNesting();
09745 }
09746
09747
09748 ON_SimpleArray<ON_Curve*> tc(trim_count);
09749 for ( eti = 0; eti < trim_count; eti++ )
09750 {
09751 const ON_BrepTrim* trim0 = Trim(trim0_index[eti]);
09752 if ( !trim0 )
09753 break;
09754 const ON_BrepTrim* trim1 = Trim(trim1_index[eti]);
09755 if ( !trim1 )
09756 break;
09757 ON_NurbsCurve* c0 = trim0->NurbsCurve();
09758 if ( !c0 )
09759 break;
09760 ON_NurbsCurve* c1 = trim1->NurbsCurve();
09761 if ( !c1 )
09762 {
09763 delete c0;
09764 break;
09765 }
09766 if ( trim0->m_vi[1] == vi_mid && trim1->m_vi[0] == vi_mid )
09767 {
09768 if ( !c0->Append(*c1) )
09769 {
09770 delete c0;
09771 delete c1;
09772 break;
09773 }
09774 delete c1;
09775 c1 = 0;
09776 tc.Append(c0);
09777 }
09778 else if ( trim0->m_vi[0] == vi_mid && trim1->m_vi[1] == vi_mid )
09779 {
09780 if ( !c1->Append(*c0) )
09781 {
09782 delete c0;
09783 delete c1;
09784 break;
09785 }
09786 delete c0;
09787 c0 = c1;
09788 c1 = 0;
09789 tc.Append(c0);
09790 }
09791 }
09792
09793 if ( eti < trim_count )
09794 {
09795 delete ec;
09796 for ( eti = 0; eti < tc.Count(); eti++ )
09797 delete tc[eti];
09798 return 0;
09799 }
09800
09801
09802
09803
09804 edge0 = 0;
09805 edge1 = 0;
09806 const int c3i = AddEdgeCurve(ec);
09807 ON_BrepEdge& edge = NewEdge( m_V[vi0], m_V[vi1], c3i );
09808 edge0 = Edge(ei0);
09809 edge1 = Edge(ei1);
09810
09811
09812 if(edge0->m_tolerance<0 || edge1->m_tolerance<0)
09813 edge.m_tolerance= ON_UNSET_VALUE;
09814 else if ( edge0->m_tolerance> edge1->m_tolerance)
09815 edge.m_tolerance= edge0->m_tolerance;
09816 else
09817 edge.m_tolerance= edge1->m_tolerance;
09818
09819
09820
09821
09822 m_T.Reserve( m_T.Count() + trim_count );
09823 for ( eti = 0; eti < trim_count; eti++ )
09824 {
09825 int c2i = AddTrimCurve( tc[eti] );
09826 ON_BrepTrim& trim0 = m_T[trim0_index[eti]];
09827 ON_BrepTrim& trim1 = m_T[trim1_index[eti]];
09828 ON_BrepTrim& trim = NewTrim( edge, trim0.m_bRev3d, c2i );
09829
09830 for(int i=0; i<2; i++){
09831 if( trim0.m_tolerance[i]<0 || trim1.m_tolerance[i]<0)
09832 trim.m_tolerance[i] = ON_UNSET_VALUE;
09833 else if(trim0.m_tolerance[i]>trim1.m_tolerance[i])
09834 trim.m_tolerance[i] = trim0.m_tolerance[i];
09835 else
09836 trim.m_tolerance[i] = trim1.m_tolerance[i];
09837 }
09838 trim.m_li = trim0.m_li;
09839 ON_BrepLoop& loop = m_L[trim.m_li];
09840 loop.m_ti[loop_lti0[eti]] = trim.m_trim_index;
09841 loop.m_ti.Remove( loop_lti1[eti] );
09842
09843
09844
09845
09846 int ri = loop_lti1[eti];
09847 int li = loop.m_loop_index;
09848 for(int ii=0; ii<trim_count; ii++){
09849 if(loop_lti0[ii]>ri && m_T[trim0_index[ii]].m_li == li)
09850 loop_lti0[ii]--;
09851 if(loop_lti1[ii]>ri && m_T[trim1_index[ii]].m_li == li)
09852 loop_lti1[ii]--;
09853 }
09854
09855
09856 trim.m_type = trim0.m_type;
09857 trim.m_iso = ON_Surface::not_iso;
09858 if( trim0.m_iso==trim1.m_iso)
09859 trim.m_iso = trim0.m_iso;
09860 trim0.m_li = -1;
09861 trim1.m_li = -1;
09862 }
09863
09864
09865 DeleteEdge(m_E[ei0],true);
09866 DeleteEdge(m_E[ei1],true);
09867
09868 return &m_E[edge.m_edge_index];
09869 }
09870
09871 bool ON_Brep::CombineCoincidentEdges(ON_BrepEdge& edge0, ON_BrepEdge& edge1)
09872 {
09873 bool rc = false;
09874 if ( edge0.m_edge_index == edge1.m_edge_index )
09875 {
09876 ON_ERROR("ON_Brep::CombineCoincidentEdges - edge0 = edge1.");
09877 return rc;
09878 }
09879 int ti, eti, etcnt;
09880 if ( edge0.m_edge_index >= 0
09881 && edge1.m_edge_index >= 0
09882 && edge0.m_edge_index != edge1.m_edge_index
09883 && edge0.m_vi[0] == edge1.m_vi[0]
09884 && edge0.m_vi[1] == edge1.m_vi[1] )
09885 {
09886 bool bIsGoodIso0 = false;
09887 if (edge0.m_tolerance == 0.0){
09888 for (eti=0; eti<edge0.m_ti.Count(); eti++){
09889 const ON_BrepTrim& T = m_T[edge0.m_ti[eti]];
09890 if (T.m_iso)
09891 {
09892 bIsGoodIso0 = true;
09893 break;
09894 }
09895 }
09896 }
09897 bool bIsGoodIso1 = false;
09898 if (edge1.m_tolerance == 0.0){
09899 for (eti=0; eti<edge1.m_ti.Count(); eti++){
09900 const ON_BrepTrim& T = m_T[edge1.m_ti[eti]];
09901 if (T.m_iso)
09902 {
09903 bIsGoodIso1 = true;
09904 break;
09905 }
09906 }
09907 }
09908 bool bKeep0 = (edge0.m_tolerance <= edge1.m_tolerance) ? true : false;
09909 if (edge0.m_tolerance == edge1.m_tolerance && edge0.m_tolerance == 0.0){
09910 if (bIsGoodIso1){
09911 if (!bIsGoodIso0)
09912 bKeep0 = false;
09913 else {
09914 if (edge1.Degree() < edge0.Degree())
09915 bKeep0 = false;
09916 else if (edge1.Degree() == edge0.Degree() && edge1.SpanCount() < edge0.SpanCount())
09917 bKeep0 = false;
09918 }
09919 }
09920 }
09921
09922 ON_BrepEdge& EKeep = (bKeep0) ? edge0 : edge1;
09923 ON_BrepEdge& EToss = (bKeep0) ? edge1 : edge0;
09924
09925
09926
09927
09928
09929
09930
09931
09932
09933
09934
09935
09936
09937
09938
09939
09940
09941
09942
09943
09944
09945
09946
09947
09948
09949
09950
09951
09952
09953
09954
09955
09956
09957
09958 rc = true;
09959 etcnt = EToss.m_ti.Count();
09960 int tcount = m_T.Count();
09961 for ( eti = 0; eti < etcnt; eti++ ) {
09962 ti = EToss.m_ti[eti];
09963 if ( ti >= 0 && ti < tcount ) {
09964 ON_BrepTrim& trim = m_T[ti];
09965 trim.m_ei = EKeep.m_edge_index;
09966 EKeep.m_ti.Append(ti);
09967 trim.UnsetPlineEdgeParameters();
09968
09969
09970
09971 if (EKeep.m_tolerance != ON_UNSET_VALUE && EToss.m_tolerance != ON_UNSET_VALUE)
09972 SetEdgeTolerance(EKeep, false);
09973 else EKeep.m_tolerance = ON_UNSET_VALUE;
09974 }
09975 }
09976 EToss.m_ti.Destroy();
09977 DeleteEdge( EToss, false );
09978
09979 etcnt = EKeep.m_ti.Count();
09980 if ( etcnt >= 2 ) for ( eti = 0; eti < etcnt; eti++ )
09981 {
09982 ti = EKeep.m_ti[eti];
09983 if ( ti >= 0 && ti < tcount )
09984 {
09985 ON_BrepTrim& trim = m_T[ti];
09986 if ( trim.m_type == ON_BrepTrim::boundary )
09987 trim.m_type = ON_BrepTrim::mated;
09988 }
09989 }
09990 }
09991 return rc;
09992 }
09993
09994 bool ON_Brep::Create( ON_Surface*& pS )
09995 {
09996 bool rc = false;
09997 Destroy();
09998 ON_Surface* p = pS;
09999 if (p)
10000 {
10001 int vid[4] = {-1,-1,-1,-1};
10002 int eid[4] = {-1,-1,-1,-1};
10003 ON_BOOL32 bRev3d[4] = {0,0,0,0};
10004 ON_BrepFace* face = NewFace(p,vid,eid,bRev3d);
10005 if ( face )
10006 {
10007 rc = true;
10008 pS = 0;
10009 }
10010 }
10011 return rc;
10012 }
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207
10208
10209
10210
10211
10212
10213 bool ON_Brep::Create( ON_NurbsSurface*& pNurbsSurface )
10214 {
10215 ON_Surface* pSurface = pNurbsSurface;
10216 bool rc = Create(pSurface);
10217 if ( !pSurface )
10218 pNurbsSurface = 0;
10219 return rc;
10220 }
10221
10222 bool ON_Brep::Create( ON_PlaneSurface*& pPlaneSurface )
10223 {
10224 ON_Surface* pSurface = pPlaneSurface;
10225 bool rc = Create(pSurface);
10226 if ( !pSurface )
10227 pPlaneSurface = 0;
10228 return rc;
10229 }
10230
10231 bool ON_Brep::Create( ON_RevSurface*& pRevSurface )
10232 {
10233 ON_Surface* pSurface = pRevSurface;
10234 bool rc = Create(pSurface);
10235 if ( !pSurface )
10236 pRevSurface = 0;
10237 return rc;
10238 }
10239
10240 bool ON_Brep::Create( ON_SumSurface*& pSumSurface )
10241 {
10242 ON_Surface* pSurface = pSumSurface;
10243 bool rc = Create(pSurface);
10244 if ( !pSurface )
10245 pSumSurface = 0;
10246 return rc;
10247 }
10248
10249
10250 ON_BOOL32 ON_Brep::HasBrepForm() const
10251 {
10252 return true;
10253 }
10254
10255 ON_Brep* ON_Brep::BrepForm( ON_Brep* brep ) const
10256 {
10257 if ( brep )
10258 {
10259 if ( brep != this )
10260 *brep = *this;
10261 }
10262 else
10263 {
10264 brep = new ON_Brep(*this);
10265 }
10266 return brep;
10267 }
10268
10269 void ON_Brep::Clear_vertex_user_i()
10270 {
10271 int vi;
10272 int vertex_count = m_V.Count();
10273 for ( vi = 0; vi < vertex_count; vi++ )
10274 {
10275 memset(&m_V[vi].m_vertex_user,0,sizeof(ON_U));
10276 }
10277 }
10278
10279 void ON_Brep::Clear_edge_user_i()
10280 {
10281 int ei;
10282 int edge_count = m_E.Count();
10283 for ( ei = 0; ei < edge_count; ei++ )
10284 {
10285 memset(&m_E[ei].m_edge_user,0,sizeof(ON_U));
10286 }
10287 }
10288
10289 void ON_Brep::Clear_edge_user_i(int i)
10290 {
10291 int ei;
10292 int edge_count = m_E.Count();
10293 for ( ei = 0; ei < edge_count; ei++ )
10294 {
10295 memset(&m_E[ei].m_edge_user,0,sizeof(ON_U));
10296 m_E[ei].m_edge_user.i = i;
10297 }
10298 }
10299
10300 void ON_Brep::Clear_trim_user_i()
10301 {
10302 int ti;
10303 int trim_count = m_T.Count();
10304 for ( ti = 0; ti < trim_count; ti++ ) {
10305 memset(&m_T[ti].m_trim_user,0,sizeof(ON_U));
10306 }
10307 }
10308
10309 void ON_Brep::Clear_loop_user_i()
10310 {
10311 int li;
10312 int loop_count = m_L.Count();
10313 for ( li = 0; li < loop_count; li++ ) {
10314 memset(&m_L[li].m_loop_user,0,sizeof(ON_U));
10315 }
10316 }
10317
10318 void ON_Brep::Clear_face_user_i()
10319 {
10320 int fi;
10321 int face_count = m_F.Count();
10322 for ( fi = 0; fi < face_count; fi++ ) {
10323 memset(&m_F[fi].m_face_user,0,sizeof(ON_U));
10324 }
10325 }
10326
10327 void ON_Brep::Clear_user_i()
10328 {
10329 memset(&m_brep_user,0,sizeof(m_brep_user));
10330 Clear_vertex_user_i();
10331 Clear_edge_user_i();
10332 Clear_trim_user_i();
10333 Clear_loop_user_i();
10334 Clear_face_user_i();
10335 }
10336
10337 void ON_Brep::Set_user(ON_U u)
10338 {
10339 int i, count;
10340 m_brep_user=u;
10341
10342 count = m_V.Count();
10343 ON_BrepVertex* V = m_V.Array();
10344 for ( i = 0; i < count; i++ )
10345 {
10346 V[i].m_vertex_user = u;
10347 }
10348
10349 count = m_E.Count();
10350 ON_BrepEdge* E = m_E.Array();
10351 for ( i = 0; i < count; i++ )
10352 {
10353 E[i].m_edge_user = u;
10354 }
10355
10356
10357 count = m_T.Count();
10358 ON_BrepTrim* T = m_T.Array();
10359 for ( i = 0; i < count; i++ )
10360 {
10361 T[i].m_trim_user = u;
10362 }
10363
10364 count = m_L.Count();
10365 ON_BrepLoop* L = m_L.Array();
10366 for ( i = 0; i < count; i++ )
10367 {
10368 L[i].m_loop_user = u;
10369 }
10370
10371 count = m_F.Count();
10372 ON_BrepFace* F = m_F.Array();
10373 for ( i = 0; i < count; i++ )
10374 {
10375 F[i].m_face_user = u;
10376 }
10377 }
10378
10379
10380
10381 ON_BrepVertex& ON_Brep::NewPointOnFace(
10382 ON_BrepFace& face,
10383 double s,
10384 double t
10385 )
10386 {
10387 ON_3dPoint point = face.PointAt(s,t);
10388
10389 ON_BrepVertex& vertex = NewVertex( point );
10390 ON_BrepLoop& loop = NewLoop( ON_BrepLoop::ptonsrf, face );
10391 ON_BrepTrim& trim = NewTrim(false,loop,-1);
10392
10393 vertex.m_tolerance = 0.0;
10394 trim.m_type = ON_BrepTrim::ptonsrf;
10395 trim.m_pbox.m_min.Set(s,t,0.0);
10396 trim.m_pbox.m_max.Set(s,t,0.0);
10397 trim.m_tolerance[0] = 0.0;
10398 trim.m_tolerance[1] = 0.0;
10399 loop.m_pbox = trim.m_pbox;
10400 trim.m_vi[0] = trim.m_vi[1] = vertex.m_vertex_index;
10401
10402 return vertex;
10403 }
10404
10405
10406 ON_BrepTrim& ON_Brep::NewCurveOnFace( ON_BrepFace& face, ON_BrepEdge& edge, ON_BOOL32 bRev3d, int c2i )
10407 {
10408 ON_BrepLoop& loop = NewLoop( ON_BrepLoop::crvonsrf, face );
10409 ON_BrepTrim& trim = NewTrim( edge, bRev3d, loop, c2i );
10410 trim.m_type = ON_BrepTrim::crvonsrf;
10411 const ON_Curve* trimcurve = trim.TrimCurveOf();
10412 if (trimcurve)
10413 {
10414 trimcurve->GetBoundingBox( trim.m_pbox );
10415 loop.m_pbox = trim.m_pbox;
10416 }
10417 return trim;
10418 }
10419
10420
10421
10422
10423
10424
10425
10426 static bool AdjustPointListAlongChord(ON_3dPointArray& Points,
10427 const ON_3dPoint& P0,
10428 const ON_3dPoint& P1)
10429
10430 {
10431 int count = Points.Count();
10432 if (count < 2)
10433 return false;
10434
10435 ON_3dPoint A0 = Points[0];
10436 ON_3dPoint A1 = Points[count-1];
10437 double chord_dist = A0.DistanceTo(A1);
10438 if (chord_dist < ON_SQRT_EPSILON)
10439 return false;
10440 double cum_dist = 0.0;
10441 int i;
10442 for (i=1; i<count; i++)
10443 cum_dist += Points[i-1].DistanceTo(Points[i]);
10444 if (chord_dist < 0.01*cum_dist)
10445 return false;
10446 ON_3dVector V0 = P0-A0;
10447 ON_3dVector V1 = P1-A1;
10448 ON_Line Aline(A0, A1);
10449 Points[0] = P0;
10450 Points[count-1] = P1;
10451 for (i=1; i<count-1; i++){
10452 double t;
10453 Aline.ClosestPointTo(Points[i], &t);
10454 Points[i] = Points[i] + (1.0-t)*V0 + t*V1;
10455 }
10456 return true;
10457 }
10458
10459 static void AdjustNurbsCurve(ON_NurbsCurve& crv,
10460 const ON_3dPoint& P0,
10461 const ON_3dPoint& P1)
10462
10463 {
10464 if (crv.Dimension() > 3)
10465 return;
10466
10467 crv.ClampEnd(2);
10468 int cvc = crv.CVCount();
10469 ON_3dPointArray Points(cvc);
10470 int i;
10471 for (i=0; i<cvc; i++)
10472 crv.GetCV(i, Points.AppendNew());
10473
10474 if (!AdjustPointListAlongChord(Points, P0, P1)){
10475 crv.SetStartPoint(P0);
10476 crv.SetEndPoint(P1);
10477 return;
10478 }
10479
10480 bool rat = crv.IsRational();
10481 for (i=0; i<cvc; i++){
10482 double w = 1.0;
10483 if (rat){
10484 w = crv.Weight(i);
10485 Points[i] *= w;
10486 }
10487 crv.SetCV(i, Points[i]);
10488 if (rat)
10489 crv.SetWeight(i, w);
10490 }
10491
10492 return;
10493 }
10494
10495 static void AdjustPolylineCurve(ON_PolylineCurve& crv,
10496 const ON_3dPoint& P0,
10497 const ON_3dPoint& P1)
10498
10499 {
10500 AdjustPointListAlongChord(crv.m_pline, P0, P1);
10501 crv.SetStartPoint(P0);
10502 crv.SetEndPoint(P1);
10503 return;
10504 }
10505
10506 static void AdjustCurve(ON_Curve& crv,
10507 const ON_3dPoint& P0,
10508 const ON_3dPoint& P1);
10509
10510 static void AdjustPolyCurve(ON_PolyCurve& crv,
10511 const ON_3dPoint& P0,
10512 const ON_3dPoint& P1)
10513
10514 {
10515
10516 if (crv.Count() == 1){
10517 ON_Curve* pSeg = crv.SegmentCurve(0);
10518 if (!pSeg)
10519 return;
10520 AdjustCurve(*pSeg, P0, P1);
10521 return;
10522 }
10523
10524 ON_3dPointArray Points(crv.Count() + 1);
10525 Points.Append(crv.PointAtStart());
10526
10527 int i;
10528 for (i=0; i<crv.Count(); i++)
10529 Points.Append(crv.SegmentCurve(i)->PointAtEnd());
10530
10531 if (!AdjustPointListAlongChord(Points, P0, P1)){
10532 crv.SetStartPoint(P0);
10533 crv.SetEndPoint(P1);
10534 return;
10535 }
10536
10537 for (i=0; i<crv.Count(); i++){
10538 ON_Curve* pSeg = crv.SegmentCurve(i);
10539 if (!pSeg)
10540 return;
10541 AdjustCurve(*pSeg, Points[i], Points[i+1]);
10542 Points[i+1] = pSeg->PointAtEnd();
10543 }
10544
10545 return;
10546 }
10547
10548
10549 static void AdjustCurve(ON_Curve& crv,
10550 const ON_3dPoint& P0,
10551 const ON_3dPoint& P1)
10552
10553 {
10554 ON_LineCurve* lc = ON_LineCurve::Cast(&crv);
10555 if (lc){
10556 lc->SetStartPoint(P0);
10557 lc->SetEndPoint(P1);
10558 return;
10559 }
10560
10561 ON_CurveProxy* pc = ON_CurveProxy::Cast(&crv);
10562 if (pc)
10563 return;
10564
10565 if (crv.IsClosed()){
10566 if (P0 != P1)
10567 return;
10568 ON_3dPoint P = crv.PointAtStart();
10569 ON_3dVector TVec = P0-P;
10570 if (TVec.Length() > ON_SQRT_EPSILON){
10571 ON_Xform T;
10572 T.Translation(TVec);
10573 crv.Transform(T);
10574 }
10575 return;
10576 }
10577
10578 ON_PolylineCurve* plc = ON_PolylineCurve::Cast(&crv);
10579 if (plc) {
10580 AdjustPolylineCurve(*plc, P0, P1);
10581 return;
10582 }
10583
10584 ON_NurbsCurve* nc = ON_NurbsCurve::Cast(&crv);
10585 if (nc){
10586 AdjustNurbsCurve(*nc, P0, P1);
10587 return;
10588 }
10589
10590 ON_PolyCurve* plyc = ON_PolyCurve::Cast(&crv);
10591 if (plyc){
10592 AdjustPolyCurve(*plyc, P0, P1);
10593 return;
10594 }
10595
10596 ON_3dPoint A0 = crv.PointAtStart();
10597 ON_3dPoint A1 = crv.PointAtEnd();
10598
10599 if (A0.DistanceTo(P0) < ON_SQRT_EPSILON && A1.DistanceTo(P1) < ON_SQRT_EPSILON){
10600 crv.SetStartPoint(P0);
10601 crv.SetEndPoint(P1);
10602 return;
10603 }
10604
10605 double alen = A0.DistanceTo(A1);
10606 double plen = P0.DistanceTo(P1);
10607 if (alen < 0.1*plen || plen < 0.1*alen){
10608 crv.SetStartPoint(P0);
10609 crv.SetEndPoint(P1);
10610 return;
10611 }
10612
10613 ON_3dPoint Ac = 0.5*(A0+A1);
10614 ON_3dPoint Pc = 0.5*(P0+P1);
10615 ON_3dVector TVec = Pc-Ac;
10616 if (TVec.Length() > ON_SQRT_EPSILON){
10617 ON_Xform T;
10618 T.Translation(TVec);
10619 crv.Transform(T);
10620 }
10621
10622 A0 = crv.PointAtStart();
10623 A1 = crv.PointAtEnd();
10624 if (A0.DistanceTo(P0) < ON_SQRT_EPSILON && A1.DistanceTo(P1) < ON_SQRT_EPSILON){
10625 crv.SetStartPoint(P0);
10626 crv.SetEndPoint(P1);
10627 return;
10628 }
10629
10630 if (fabs(plen - alen) > ON_SQRT_EPSILON){
10631 double scale = plen/alen;
10632 Ac = 0.5*(A0+A1);
10633 ON_Xform T;
10634 T.Scale(Ac, scale);
10635 crv.Transform(T);
10636 }
10637
10638 A0 = crv.PointAtStart();
10639 A1 = crv.PointAtEnd();
10640 if (A0.DistanceTo(P0) < ON_SQRT_EPSILON && A1.DistanceTo(P1) < ON_SQRT_EPSILON){
10641 crv.SetStartPoint(P0);
10642 crv.SetEndPoint(P1);
10643 return;
10644 }
10645
10646 if (plen < ON_SQRT_EPSILON){
10647 crv.SetStartPoint(P0);
10648 crv.SetEndPoint(P1);
10649 return;
10650 }
10651
10652 ON_3dPoint C = 0.5*(Pc+Ac);
10653 ON_3dVector VA = A0-C;
10654 VA.Unitize();
10655 ON_3dVector VP = P0-C;
10656 VP.Unitize();
10657
10658 ON_3dVector Axis = ON_CrossProduct(VA, VP);
10659 double sina = Axis.Length();
10660 if (sina < ON_SQRT_EPSILON){
10661 crv.SetStartPoint(P0);
10662 crv.SetEndPoint(P1);
10663 return;
10664 }
10665 Axis.Unitize();
10666 double cosa = VA*VP;
10667
10668 ON_Xform T;
10669 T.Rotation(sina, cosa, Axis, C);
10670 crv.Transform(T);
10671 crv.SetStartPoint(P0);
10672 crv.SetEndPoint(P1);
10673 return;
10674 }
10675
10676 static void AdjustEdgeEnds(ON_BrepEdge& edge)
10677
10678 {
10679 ON_Brep* pB = edge.Brep();
10680 if (!pB)
10681 return;
10682 ON_Curve* c3 = const_cast<ON_Curve*>(edge.EdgeCurveOf());
10683 if( c3 )
10684 {
10685 ON_3dPoint A0 = c3->PointAtStart();
10686 ON_3dPoint P0 = A0;
10687 if (edge.m_vi[0] >= 0){
10688 ON_BrepVertex& V = pB->m_V[edge.m_vi[0]];
10689 if (V.IsValid())
10690 P0 = V.Point();
10691 }
10692 ON_3dPoint A1 = c3->PointAtEnd();
10693 ON_3dPoint P1 = A1;
10694 if (edge.m_vi[1] >= 0){
10695 ON_BrepVertex& V = pB->m_V[edge.m_vi[1]];
10696 if (V.IsValid())
10697 P1 = V.Point();
10698 }
10699
10700 bool bQuit = true;
10701 if (P0 != A0 && edge.m_vi[0] >= 0){
10702 ON_BrepVertex& V = pB->m_V[edge.m_vi[0]];
10703 V.m_tolerance = ON_UNSET_VALUE;
10704 bQuit = false;
10705 }
10706 if (P1 != A1 && edge.m_vi[1] >= 0){
10707 ON_BrepVertex& V = pB->m_V[edge.m_vi[1]];
10708 V.m_tolerance = ON_UNSET_VALUE;
10709 bQuit = false;
10710 }
10711 if (bQuit)
10712 return;
10713
10714 edge.m_tolerance = ON_UNSET_VALUE;
10715 AdjustCurve(*c3, P0, P1);
10716 }
10717 return;
10718 }
10719
10720 bool ON_Brep::StandardizeEdgeCurve( int edge_index, bool bAdjustEnds )
10721 {
10722 return StandardizeEdgeCurve(edge_index, bAdjustEnds, 0);
10723 }
10724
10725 bool ON_Brep::StandardizeEdgeCurve( int edge_index, bool bAdjustEnds, int EdgeCurveUse )
10726 {
10727 bool rc = false;
10728 ON_BrepEdge* edge = Edge(edge_index);
10729 if ( 0 != edge && edge->m_edge_index >= 0 )
10730 {
10731 edge_index = edge->m_edge_index;
10732 const ON_Curve* c3 = edge->EdgeCurveOf();
10733 if( c3 )
10734 {
10735 ON_Interval c3dom = c3->Domain();
10736 ON_Interval pdom = edge->ProxyCurveDomain();
10737 ON_Interval edom = edge->Domain();
10738 bool bNewCurve = false;
10739 if ( edge->ProxyCurveIsReversed() )
10740 bNewCurve = true;
10741 else if ( c3dom != pdom )
10742 bNewCurve = true;
10743 else if ( EdgeCurveUse > 1 || (EdgeCurveUse < 1 && EdgeCurveUseCount( edge->m_c3i,2 ) > 1 ))
10744 bNewCurve = true;
10745 else if ( edom != c3dom )
10746 {
10747
10748
10749 if ( m_C3[edge->m_c3i]->SetDomain(edom) )
10750 {
10751 edge->SetProxyCurveDomain(edom);
10752 edge->SetDomain(edom);
10753 rc = true;
10754 }
10755 else
10756 {
10757 bNewCurve = true;
10758 }
10759 }
10760 else
10761 rc = true;
10762
10763 if ( bNewCurve )
10764 {
10765 ON_Curve* newc3 = c3->Duplicate();
10766 if ( !newc3 )
10767 return false;
10768 if ( !newc3->Trim(pdom) )
10769 {
10770 delete newc3;
10771 return false;
10772 }
10773 if ( edge->ProxyCurveIsReversed() )
10774 {
10775 if ( !newc3->Reverse() )
10776 {
10777 delete newc3;
10778 return false;
10779 }
10780 }
10781 newc3->SetDomain(edom);
10782 if ( newc3->Domain() != edom )
10783 {
10784 delete newc3;
10785 return false;
10786 }
10787 int c3i = AddEdgeCurve(newc3);
10788 edge->m_c3i = c3i;
10789 edge->SetProxyCurve(newc3);
10790 }
10791 }
10792 }
10793 if (rc && bAdjustEnds)
10794 AdjustEdgeEnds(*edge);
10795
10796
10797
10798
10799
10800
10801
10802
10803
10804
10805
10806
10807
10808
10809
10810
10811
10812
10813
10814
10815
10816 return rc;
10817 }
10818
10819 static int sort_ci(const ON_BrepEdge* E0, const ON_BrepEdge* E1)
10820
10821 {
10822 if (E0->m_c3i < E1->m_c3i)
10823 return -1;
10824 if (E0->m_c3i < E1->m_c3i)
10825 return 1;
10826 return 0;
10827 }
10828
10829
10830 void ON_Brep::StandardizeEdgeCurves( bool bAdjustEnds)
10831 {
10832
10833
10834
10835
10836
10837 int ei, edge_count = m_E.Count();
10838
10839
10840
10841
10842 int* index = (int*)onmalloc(edge_count*sizeof(int));
10843 m_E.Sort(ON::quick_sort, index, sort_ci);
10844
10845 for ( ei = 0; ei < edge_count; ei++ ){
10846 int ecc = (ei==edge_count-1 || m_E[index[ei+1]].m_c3i == m_E[index[ei]].m_c3i) ? 2 : 1;
10847 StandardizeEdgeCurve( index[ei], false, ecc);
10848 }
10849
10850 onfree((void*)index);
10851
10852
10853
10854
10855
10856
10857
10858
10859 if (bAdjustEnds){
10860 for ( ei = 0; ei < edge_count; ei++ )
10861 AdjustEdgeEnds(m_E[ei]);
10862 SetVertexTolerances(true);
10863 SetEdgeTolerances(true);
10864 }
10865 }
10866
10867 bool ON_Brep::StandardizeTrimCurve( int trim_index )
10868 {
10869 bool rc = false;
10870 ON_BrepTrim* trim = Trim(trim_index);
10871 if ( 0 != trim && trim->m_trim_index >= 0 )
10872 {
10873 trim_index = trim->m_trim_index;
10874 const ON_Curve* c2 = trim->TrimCurveOf();
10875 if( c2 )
10876 {
10877 ON_Interval c2dom = c2->Domain();
10878 ON_Interval pdom = trim->ProxyCurveDomain();
10879 ON_Interval tdom = trim->Domain();
10880 bool bNewCurve = false;
10881 if ( trim->ProxyCurveIsReversed() )
10882 bNewCurve = true;
10883 else if ( c2dom != pdom )
10884 bNewCurve = true;
10885 else if ( TrimCurveUseCount( trim->m_c2i, 2 ) > 1 )
10886 bNewCurve = true;
10887 else if ( tdom != c2dom )
10888 {
10889
10890
10891 if ( m_C2[trim->m_c2i]->SetDomain(tdom) )
10892 {
10893 trim->SetProxyCurveDomain(tdom);
10894 trim->SetDomain(tdom);
10895 rc = true;
10896 }
10897 else
10898 {
10899 bNewCurve = true;
10900 }
10901 }
10902 else
10903 rc = true;
10904
10905 if ( bNewCurve )
10906 {
10907 ON_Curve* newc2 = c2->Duplicate();
10908 if ( !newc2 )
10909 return false;
10910 if ( !newc2->Trim(pdom) )
10911 {
10912 delete newc2;
10913 return false;
10914 }
10915 if ( trim->ProxyCurveIsReversed() )
10916 {
10917 if ( !newc2->Reverse() )
10918 {
10919 delete newc2;
10920 return false;
10921 }
10922 }
10923 newc2->SetDomain(tdom);
10924 if ( newc2->Domain() != tdom )
10925 {
10926 delete newc2;
10927 return false;
10928 }
10929 int c2i = AddTrimCurve(newc2);
10930 trim->m_c2i = c2i;
10931 trim->SetProxyCurve(newc2);
10932 rc = true;
10933 }
10934 }
10935 }
10936 return rc;
10937 }
10938
10939 void ON_Brep::StandardizeTrimCurves()
10940 {
10941 int ti, trim_count = m_T.Count();
10942 for ( ti = 0; ti < trim_count; ti++ )
10943 {
10944 StandardizeTrimCurve( ti );
10945 }
10946 }
10947
10948 bool ON_Brep::StandardizeFaceSurface( int face_index )
10949 {
10950 bool rc = false;
10951 ON_BrepFace* face = Face(face_index);
10952 if ( 0 != face && face->m_face_index >= 0 )
10953 {
10954 face_index = face->m_face_index;
10955 const ON_Surface* srf = face->SurfaceOf();
10956 if ( srf )
10957 {
10958 if ( face->m_bRev )
10959 {
10960 if ( SurfaceUseCount( face->m_si, 2 ) >= 2 )
10961 {
10962 ON_Surface* newsrf = srf->Duplicate();
10963 face->m_si = AddSurface(newsrf);
10964 face->SetProxySurface(m_S[face->m_si]);
10965 srf = newsrf;
10966 }
10967 rc = face->Transpose() ? true : false;
10968 }
10969 else
10970 rc = true;
10971 }
10972 }
10973 return rc;
10974 }
10975
10976 void ON_Brep::StardardizeFaceSurfaces()
10977 {
10978
10979
10980 StandardizeFaceSurfaces();
10981 }
10982
10983 void ON_Brep::StandardizeFaceSurfaces()
10984 {
10985 int fi, face_count = m_F.Count();
10986 for ( fi = 0; fi < face_count; fi++ )
10987 {
10988 StandardizeFaceSurface( fi );
10989 }
10990 }
10991
10992 void ON_Brep::Standardize()
10993 {
10994 StandardizeFaceSurfaces();
10995 StandardizeEdgeCurves(true);
10996 StandardizeTrimCurves();
10997 }
10998
10999
11000
11001 bool ON_Brep::ShrinkSurface( ON_BrepFace& face, int DisableMask )
11002 {
11003 ON_Surface* srf = const_cast<ON_Surface*>(face.SurfaceOf());
11004 if ( !srf )
11005 return false;
11006
11007 ON_Interval srf_udom = srf->Domain(0);
11008 ON_Interval srf_vdom = srf->Domain(1);
11009
11010 int fli, li, si=-1;
11011 int lti, ti;
11012 int outer_loop_li=-1;
11013 const int loop_count = m_L.Count();
11014 const int trim_count = m_T.Count();
11015 ON_BoundingBox outer_pbox;
11016
11017 bool bAllTrimsAreIsoTrims = true;
11018 bool bSomeTrimsAreIsoTrims = false;
11019
11020
11021
11022 ON_BoundingBox trim_iso_endbox;
11023
11024 int face_loop_count = face.m_li.Count();
11025 bool bIsSrfEdge[4];
11026 int sei;
11027 for (sei=0; sei<4; sei++)
11028 bIsSrfEdge[sei] = false;
11029 for ( fli = 0; fli < face_loop_count; fli++ )
11030 {
11031 li = face.m_li[fli];
11032 if ( li < 0 )
11033 continue;
11034 if ( li >= loop_count )
11035 continue;
11036 const ON_BrepLoop& loop = m_L[li];
11037 if ( loop.m_type == ON_BrepLoop::outer )
11038 {
11039
11040 if ( outer_loop_li )
11041 outer_loop_li = li;
11042 outer_pbox.Union( loop.m_pbox );
11043
11044 int loop_trim_count = loop.m_ti.Count();
11045 for ( lti = 0; lti < loop_trim_count; lti++ )
11046 {
11047 ti = loop.m_ti[lti];
11048 if ( ti >= 0 && ti < trim_count )
11049 {
11050 bool bIsIso = false;
11051 switch( m_T[ti].m_iso )
11052 {
11053 case ON_Surface::x_iso:
11054 case ON_Surface::y_iso:
11055 bIsIso = true;
11056 break;
11057 case ON_Surface::W_iso:
11058 bIsIso = true;
11059 bIsSrfEdge[0] = true;
11060 break;
11061 case ON_Surface::S_iso:
11062 bIsIso = true;
11063 bIsSrfEdge[1] = true;
11064 break;
11065 case ON_Surface::E_iso:
11066 bIsIso = true;
11067 bIsSrfEdge[2] = true;
11068 break;
11069 case ON_Surface::N_iso:
11070 bIsIso = true;
11071 bIsSrfEdge[3] = true;
11072 break;
11073 default:
11074
11075 bAllTrimsAreIsoTrims = false;
11076 }
11077 if (bIsIso){
11078
11079 trim_iso_endbox.Set( m_T[ti].PointAtStart(), true );
11080 trim_iso_endbox.Set( m_T[ti].PointAtEnd(), true );
11081 bSomeTrimsAreIsoTrims = true;
11082 }
11083 }
11084 }
11085
11086 }
11087 }
11088
11089 if ( !outer_pbox.IsValid() )
11090 return false;
11091
11092 bool rc = false;
11093 ON_Interval outer_udom( outer_pbox.m_min.x, outer_pbox.m_max.x );
11094 ON_Interval outer_vdom( outer_pbox.m_min.y, outer_pbox.m_max.y );
11095
11096 if ( !bAllTrimsAreIsoTrims )
11097 {
11098
11099
11100
11101
11102
11103
11104 double d;
11105
11106 d = outer_udom.Length()*0.01;
11107 if ( (!bSomeTrimsAreIsoTrims || outer_udom[0] < trim_iso_endbox.m_min.x) && !bIsSrfEdge[0] )
11108 outer_udom[0] -= d;
11109 if ( (!bSomeTrimsAreIsoTrims || outer_udom[1] > trim_iso_endbox.m_max.x) && !bIsSrfEdge[2])
11110 outer_udom[1] += d;
11111
11112 d = outer_vdom.Length()*0.01;
11113 if ( (!bSomeTrimsAreIsoTrims || outer_vdom[0] < trim_iso_endbox.m_min.y) && !bIsSrfEdge[1] )
11114 outer_vdom[0] -= d;
11115 if ( (!bSomeTrimsAreIsoTrims || outer_vdom[1] > trim_iso_endbox.m_max.y) && !bIsSrfEdge[3] )
11116 outer_vdom[1] += d;
11117 }
11118
11119 outer_udom.Intersection( srf_udom );
11120 outer_vdom.Intersection( srf_vdom );
11121
11122 bool bShrinkIt = false;
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143 if( DisableMask & 0x0001)
11144 outer_udom[0] = srf_udom[0];
11145 if( DisableMask & 0x0002)
11146 outer_vdom[0] = srf_vdom[0];
11147 if( DisableMask & 0x0004)
11148 outer_udom[1] = srf_udom[1];
11149 if( DisableMask & 0x0008)
11150 outer_vdom[1] = srf_vdom[1];
11151
11152
11153
11154 if ( outer_udom.IsIncreasing() && outer_vdom.IsIncreasing() )
11155 {
11156
11157
11158 if ( outer_udom.Length()*ON_ZERO_TOLERANCE < (srf_udom.Length() - outer_udom.Length()) ||
11159 outer_vdom.Length()*ON_ZERO_TOLERANCE < (srf_vdom.Length() - outer_vdom.Length()) )
11160 bShrinkIt = true;
11161 }
11162
11163 if ( bShrinkIt )
11164 {
11165 int srf_use = SurfaceUseCount( face.m_si, 2);
11166 ON_Surface* small_srf = srf->Duplicate();
11167 if ( small_srf->Trim( 0, outer_udom ) )
11168 {
11169 if ( small_srf->Trim( 1, outer_vdom) )
11170 si = AddSurface(small_srf);
11171 if ( si >= 0 )
11172 {
11173 int srf_index = face.m_si;
11174 face.m_si = si;
11175 face.SetProxySurface( m_S[face.m_si] );
11176
11177
11178 if (srf_use == 1) DeleteSurface(srf_index);
11179
11180
11181 face.m_bbox = small_srf->BoundingBox();
11182 m_bbox.Destroy();
11183
11184
11185 for(int li=0; li<face.LoopCount(); li++){
11186 ON_BrepLoop& loop = *face.Loop(li);
11187 for(int ti=0; ti<loop.TrimCount(); ti++){
11188 ON_BrepTrim& trim = *loop.Trim(ti);
11189
11190
11191
11192
11193
11194
11195
11196 if (trim.m_iso != ON_Surface::not_iso)
11197 trim.m_iso = face.IsIsoparametric(trim);
11198 }
11199 }
11200 rc = true;
11201 }
11202 }
11203 if ( !rc )
11204 delete small_srf;
11205 }
11206
11207 return rc;
11208 }
11209
11210 bool ON_Brep::ShrinkSurfaces()
11211 {
11212 bool rc = true;
11213 int fi, face_count = m_F.Count();
11214 for ( fi = 0; fi < face_count; fi++ )
11215 {
11216 if ( !ShrinkSurface( m_F[fi] ) )
11217 rc = false;
11218 }
11219 Compact();
11220 return rc;
11221 }
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248
11249
11250
11251
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287
11288 const ON_Geometry* ON_Brep::BrepComponent(
11289 ON_COMPONENT_INDEX ci
11290 ) const
11291 {
11292 const ON_Geometry* component = 0;
11293 switch ( ci.m_type )
11294 {
11295 case ON_COMPONENT_INDEX::brep_vertex:
11296 component = Vertex(ci.m_index);
11297 break;
11298 case ON_COMPONENT_INDEX::brep_edge:
11299 component = Edge(ci.m_index);
11300 break;
11301 case ON_COMPONENT_INDEX::brep_face:
11302 component = Face(ci.m_index);
11303 break;
11304 case ON_COMPONENT_INDEX::brep_trim:
11305 component = Trim(ci.m_index);
11306 break;
11307 case ON_COMPONENT_INDEX::brep_loop:
11308 component = Loop(ci.m_index);
11309 break;
11310 default:
11311
11312 break;
11313 }
11314 return component;
11315 }
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349 ON_BrepVertex* ON_Brep::Vertex( int vertex_index ) const
11350 {
11351 ON_BrepVertex* vertex = 0;
11352 if ( vertex_index>=0 && vertex_index < m_V.Count() )
11353 vertex = const_cast<ON_BrepVertex*>(&m_V[vertex_index]);
11354 return vertex;
11355 }
11356
11357 ON_BrepVertex* ON_Brep::Vertex( ON_COMPONENT_INDEX vertex_index ) const
11358 {
11359 ON_BrepVertex* vertex = 0;
11360 if ( ON_COMPONENT_INDEX::brep_vertex == vertex_index.m_type
11361 && vertex_index.m_index >= 0
11362 && vertex_index.m_index < m_V.Count() )
11363 {
11364 vertex = const_cast<ON_BrepVertex*>(&m_V[vertex_index.m_index]);
11365 }
11366 return vertex;
11367 }
11368
11369
11370 ON_BrepEdge* ON_Brep::Edge( int edge_index ) const
11371 {
11372 ON_BrepEdge* edge = 0;
11373 if ( edge_index>=0 && edge_index < m_E.Count() )
11374 edge = const_cast<ON_BrepEdge*>(&m_E[edge_index]);
11375 return edge;
11376 }
11377
11378 ON_BrepEdge* ON_Brep::Edge( ON_COMPONENT_INDEX edge_index ) const
11379 {
11380 ON_BrepEdge* edge = 0;
11381 if ( ON_COMPONENT_INDEX::brep_edge == edge_index.m_type
11382 && edge_index.m_index >= 0
11383 && edge_index.m_index < m_E.Count() )
11384 {
11385 edge = const_cast<ON_BrepEdge*>(&m_E[edge_index.m_index]);
11386 }
11387 return edge;
11388 }
11389
11390 ON_BrepTrim* ON_Brep::Trim( int trim_index ) const
11391 {
11392 ON_BrepTrim* trim = 0;
11393 if ( trim_index>=0 && trim_index < m_T.Count() )
11394 trim = const_cast<ON_BrepTrim*>(&m_T[trim_index]);
11395 return trim;
11396 }
11397
11398 ON_BrepTrim* ON_Brep::Trim( ON_COMPONENT_INDEX trim_index ) const
11399 {
11400 ON_BrepTrim* trim = 0;
11401 if ( ON_COMPONENT_INDEX::brep_trim == trim_index.m_type
11402 && trim_index.m_index >= 0
11403 && trim_index.m_index < m_T.Count() )
11404 {
11405 trim = const_cast<ON_BrepTrim*>(&m_T[trim_index.m_index]);
11406 }
11407 return trim;
11408 }
11409
11410 ON_BrepLoop* ON_Brep::Loop( int loop_index ) const
11411 {
11412 ON_BrepLoop* loop = 0;
11413 if ( loop_index>=0 && loop_index < m_L.Count() )
11414 loop = const_cast<ON_BrepLoop*>(&m_L[loop_index]);
11415 return loop;
11416 }
11417
11418 ON_BrepLoop* ON_Brep::Loop( ON_COMPONENT_INDEX loop_index ) const
11419 {
11420 ON_BrepLoop* loop = 0;
11421 if ( ON_COMPONENT_INDEX::brep_loop == loop_index.m_type
11422 && loop_index.m_index >= 0
11423 && loop_index.m_index < m_L.Count() )
11424 {
11425 loop = const_cast<ON_BrepLoop*>(&m_L[loop_index.m_index]);
11426 }
11427 return loop;
11428 }
11429
11430 ON_BrepFace* ON_Brep::Face( int face_index ) const
11431 {
11432 ON_BrepFace* face = 0;
11433 if ( face_index>=0 && face_index < m_F.Count() )
11434 face = const_cast<ON_BrepFace*>(&m_F[face_index]);
11435 return face;
11436 }
11437
11438 ON_BrepFace* ON_Brep::Face( ON_COMPONENT_INDEX face_index ) const
11439 {
11440 ON_BrepFace* face = 0;
11441 if ( ON_COMPONENT_INDEX::brep_face == face_index.m_type
11442 && face_index.m_index >= 0
11443 && face_index.m_index < m_F.Count() )
11444 {
11445 face = const_cast<ON_BrepFace*>(&m_F[face_index.m_index]);
11446 }
11447 return face;
11448 }
11449
11450 const ON_Surface* ON_BrepFace::SurfaceOf() const
11451 {
11452 const ON_Surface* srf = ProxySurface();
11453 if ( 0 == srf && 0 != m_brep && m_si >= 0 && m_si < m_brep->m_S.Count() )
11454 {
11455 srf = m_brep->m_S[m_si];
11456 }
11457 return srf;
11458 }
11459
11460
11461
11462 void ON_BrepTrim::DestroyPspaceInformation()
11463 {
11464 m_pline.Destroy();
11465 m_pbox.Destroy();
11466 }
11467
11468 bool ON_BrepTrim::ChangeTrimCurve( int c2i )
11469 {
11470 if ( 0 == m_brep )
11471 return 0;
11472 if ( c2i < 0 || c2i >= m_brep->m_C2.Count() )
11473 return 0;
11474 const ON_Curve* c2 = m_brep->m_C2[c2i];
11475 m_c2i = c2i;
11476 DestroyPspaceInformation();
11477 SetProxyCurve(c2);
11478 if ( c2 )
11479 {
11480 m_pbox = c2->BoundingBox();
11481 m_pbox.m_min.z = 0.0;
11482 m_pbox.m_max.z = 0.0;
11483 }
11484 return true;
11485 }
11486
11487 bool ON_BrepTrim::RemoveFromEdge(
11488 bool bRemoveFromStartVertex,
11489 bool bRemoveFromEndVertex
11490 )
11491 {
11492 bool rc = false;
11493 if ( 0 != m_brep || m_ei < 0 )
11494 {
11495 UnsetPlineEdgeParameters();
11496 if ( 0 != m_brep )
11497 {
11498 ON_BrepEdge* edge = m_brep->Edge(m_ei);
11499 if ( 0 != edge )
11500 {
11501 int eti = 0;
11502 while( eti < edge->m_ti.Count() )
11503 {
11504 if ( edge->m_ti[eti] == m_trim_index )
11505 edge->m_ti.Remove(eti);
11506 else
11507 eti++;
11508 }
11509 }
11510 }
11511 m_ei = -1;
11512 if (bRemoveFromStartVertex)
11513 m_vi[0] = -1;
11514 if (bRemoveFromEndVertex)
11515 m_vi[1] = -1;
11516 rc = true;
11517 }
11518 return rc;
11519 }
11520
11521 bool ON_BrepTrim::AttachToEdge(
11522 int edge_index,
11523 bool bRev3d
11524 )
11525 {
11526 bool rc = false;
11527 if ( 0 != m_brep )
11528 {
11529 ON_BrepEdge* edge = m_brep->Edge(edge_index);
11530 if ( 0 != edge )
11531 {
11532 rc = RemoveFromEdge(true,true);
11533 if (rc)
11534 {
11535 edge->m_ti.Append(m_trim_index);
11536 m_ei = edge->m_edge_index;
11537 m_bRev3d = bRev3d ? true : false;
11538 m_vi[0] = edge->m_vi[bRev3d?1:0];
11539 m_vi[1] = edge->m_vi[bRev3d?0:1];
11540 }
11541 }
11542 }
11543 return rc;
11544 }
11545
11546
11547
11548 const ON_Curve* ON_BrepEdge::EdgeCurveOf() const
11549 {
11550 const ON_Curve* c3 = ProxyCurve();
11551 if ( !c3 && m_brep && m_c3i >= 0 && m_c3i < m_brep->m_C3.Count())
11552 {
11553
11554
11555 c3 = m_brep->m_C3[m_c3i];
11556 if ( c3 )
11557 {
11558 ON_ERROR("ON_BrepEdge ProxyCurve() is NULL but m_c3i is valid");
11559 }
11560 }
11561 return c3;
11562 }
11563
11564 int ON_BrepEdge::EdgeCurveIndexOf() const
11565 {
11566 return (m_brep && m_c3i >= 0 && m_c3i < m_brep->m_C3.Count()) ? m_c3i : -1;
11567 }
11568
11569 int ON_BrepTrim::EdgeCurveIndexOf() const
11570 {
11571 int c3i = -1;
11572 if ( m_brep && m_ei >= 0 && m_ei < m_brep->m_E.Count() )
11573 {
11574 c3i = m_brep->m_E[m_ei].m_c3i;
11575 if ( c3i < 0 || c3i >= m_brep->m_C3.Count() )
11576 c3i = -1;
11577 }
11578 return c3i;
11579 }
11580
11581 int ON_BrepTrim::TrimCurveIndexOf() const
11582 {
11583 return ((m_brep && m_c2i >= 0 && m_c2i < m_brep->m_C2.Count()) ? m_c2i : -1);
11584 }
11585
11586 const ON_Curve* ON_BrepTrim::EdgeCurveOf() const
11587 {
11588 const ON_Curve* c3 = 0;
11589 if ( m_brep && m_ei >= 0 && m_ei < m_brep->m_C3.Count() )
11590 {
11591 c3 = m_brep->m_E[m_ei].EdgeCurveOf();
11592 }
11593 return c3;
11594 }
11595
11596 bool ON_BrepEdge::ChangeEdgeCurve( int c3i )
11597 {
11598 if ( 0 == m_brep )
11599 return 0;
11600 if ( c3i < 0 || c3i >= m_brep->m_C3.Count() )
11601 return 0;
11602 const ON_Curve* c3 = m_brep->m_C3[c3i];
11603 m_c3i = c3i;
11604 SetProxyCurve(c3);
11605 UnsetPlineEdgeParameters();
11606 return true;
11607 }
11608
11609 const ON_Curve* ON_BrepTrim::TrimCurveOf() const
11610 {
11611 const ON_Curve* c2 = ProxyCurve();
11612 if ( !c2 && m_brep && m_c2i >= 0 && m_c2i < m_brep->m_C2.Count() )
11613 {
11614
11615
11616 c2 = m_brep->m_C2[m_c2i];
11617 if ( c2 )
11618 {
11619 ON_ERROR("ON_BrepTrim ProxyCurve() = NULL but m_c2i is valid");
11620 }
11621 }
11622 return c2;
11623 }
11624
11625 const ON_Surface* ON_BrepTrim::SurfaceOf() const
11626 {
11627 const ON_Surface* srf = 0;
11628 if ( m_brep && m_li >= 0 && m_li < m_brep->m_L.Count() )
11629 {
11630 const int fi = m_brep->m_L[m_li].m_fi;
11631 if ( fi >= 0 && fi < m_brep->m_F.Count() )
11632 {
11633 srf = m_brep->m_F[fi].SurfaceOf();
11634 }
11635 }
11636 return srf;
11637 }
11638
11639 const ON_Surface* ON_BrepLoop::SurfaceOf() const
11640 {
11641 const ON_Surface* srf = 0;
11642 if ( m_brep && m_fi >= 0 && m_fi < m_brep->m_F.Count() )
11643 {
11644 srf = m_brep->m_F[m_fi].SurfaceOf();
11645 }
11646 return srf;
11647 }
11648
11649 int ON_BrepTrim::SurfaceIndexOf() const
11650 {
11651 int si = -1;
11652 if ( m_brep && m_li >= 0 && m_li < m_brep->m_L.Count() )
11653 {
11654 const int fi = m_brep->m_L[m_li].m_fi;
11655 if ( fi >= 0 && fi < m_brep->m_F.Count() )
11656 {
11657 si = m_brep->m_F[fi].m_si;
11658 if ( si < 0 || si >= m_brep->m_S.Count() )
11659 si = -1;
11660 }
11661 }
11662 return si;
11663 }
11664
11665
11666 int ON_BrepTrim::FaceIndexOf() const
11667 {
11668 int fi = -1;
11669 if ( m_brep && m_li >= 0 && m_li < m_brep->m_L.Count() )
11670 {
11671 fi = m_brep->m_L[m_li].m_fi;
11672 if ( fi< 0 || fi >= m_brep->m_F.Count() )
11673 {
11674 fi = -1;
11675 }
11676 }
11677 return fi;
11678 }
11679
11680 static
11681 const ON_BrepTrim* SlitSeamMateHelper( const ON_BrepTrim& trim )
11682 {
11683 if ( ON_BrepTrim::seam != trim.m_type )
11684 return 0;
11685 if ( trim.m_li < 0 )
11686 return 0;
11687 if ( trim.m_ei < 0 )
11688 return 0;
11689 const ON_Brep* brep = trim.Brep();
11690 if ( !brep )
11691 return 0;
11692 if ( trim.m_ei >= brep->m_E.Count() )
11693 return 0;
11694 const ON_BrepEdge& edge = brep->m_E[trim.m_ei];
11695 int other_ti = -1;
11696 for ( int eti = 0; eti < edge.m_ti.Count(); eti++ )
11697 {
11698 int ti = edge.m_ti[eti];
11699 if ( trim.m_trim_index == ti )
11700 continue;
11701 if ( ti < 0 || ti >= brep->m_T.Count() )
11702 continue;
11703 if ( trim.m_li == brep->m_T[ti].m_li )
11704 {
11705 if (other_ti >= 0 )
11706 return 0;
11707 other_ti = ti;
11708 }
11709 }
11710 if ( other_ti < 0 )
11711 return 0;
11712 return &brep->m_T[other_ti];
11713 }
11714
11715 bool ON_BrepTrim::IsSlit() const
11716 {
11717
11718
11719
11720
11721
11722 switch(m_iso)
11723 {
11724 case ON_Surface::E_iso:
11725 case ON_Surface::N_iso:
11726 case ON_Surface::S_iso:
11727 case ON_Surface::W_iso:
11728 return false;
11729 break;
11730
11731 case ON_Surface::not_iso:
11732 case ON_Surface::x_iso:
11733 case ON_Surface::y_iso:
11734 case ON_Surface::iso_count:
11735
11736 break;
11737 }
11738 const ON_BrepTrim* other_trim = SlitSeamMateHelper(*this);
11739 if ( !other_trim )
11740 return false;
11741 return ( other_trim->m_iso == m_iso );
11742 }
11743
11744 bool ON_BrepTrim::IsSeam() const
11745 {
11746
11747
11748
11749
11750
11751 ON_Surface::ISO other_iso = ON_Surface::not_iso;
11752 switch(m_iso)
11753 {
11754 case ON_Surface::E_iso:
11755 other_iso = ON_Surface::W_iso;
11756 break;
11757 case ON_Surface::N_iso:
11758 other_iso = ON_Surface::S_iso;
11759 break;
11760 case ON_Surface::S_iso:
11761 other_iso = ON_Surface::N_iso;
11762 break;
11763 case ON_Surface::W_iso:
11764 other_iso = ON_Surface::E_iso;
11765 break;
11766 default:
11767 return false;
11768 }
11769 const ON_BrepTrim* other_trim = SlitSeamMateHelper(*this);
11770 if ( !other_trim )
11771 return false;
11772
11773 return ( other_trim->m_iso == other_iso );
11774 }
11775
11776
11777 int ON_BrepLoop::SurfaceIndexOf() const
11778 {
11779 const ON_BrepFace* face = Face();
11780 return face ? face->m_si : -1;
11781 }
11782
11783 int ON_BrepFace::SurfaceIndexOf() const
11784 {
11785 return (m_brep && m_si >= 0 && m_si < m_brep->m_S.Count()) ? m_si : 0;
11786 }
11787
11788 void ON_BrepTrim::UnsetPlineEdgeParameters()
11789 {
11790 int count = m_pline.Count();
11791 if ( count > 0 )
11792 {
11793 ON_BrepTrimPoint* pline = m_pline.Array();
11794 while ( count-- )
11795 (pline++)->e = ON_UNSET_VALUE;
11796 }
11797 }
11798
11799 void ON_BrepEdge::UnsetPlineEdgeParameters()
11800 {
11801 int edge_trim_count, brep_trim_count, eti, ti;
11802 if ( 0 != m_brep )
11803 {
11804 edge_trim_count = m_ti.Count();
11805 if ( edge_trim_count > 0 )
11806 {
11807 brep_trim_count = m_brep->m_T.Count();
11808 for ( eti = 0; eti < edge_trim_count; eti++ )
11809 {
11810 ti = m_ti[eti];
11811 if ( ti >= 0 && ti < brep_trim_count )
11812 {
11813 m_brep->m_T[ti].UnsetPlineEdgeParameters();
11814 }
11815 }
11816 }
11817 }
11818 }
11819
11820 bool ON_BrepFace::TransformTrim( const ON_Xform& xform )
11821 {
11822 if ( !m_brep )
11823 return false;
11824 int fli;
11825 for ( fli = 0; fli < m_li.Count(); fli++ )
11826 {
11827 ON_BrepLoop* loop = m_brep->Loop( m_li[fli] );
11828 if ( loop )
11829 {
11830 if ( !loop->TransformTrim(xform) )
11831 return false;
11832 }
11833 }
11834 return true;
11835 }
11836
11837 bool ON_BrepLoop::TransformTrim( const ON_Xform& xform )
11838 {
11839 if ( !m_brep )
11840 return false;
11841 int lti;
11842 m_pbox.Destroy();
11843 for ( lti = 0; lti < m_ti.Count(); lti++ )
11844 {
11845 ON_BrepTrim* trim = m_brep->Trim( m_ti[lti] );
11846 if ( trim )
11847 {
11848 if ( !trim->TransformTrim(xform) )
11849 return false;
11850 m_pbox.Union( trim->m_pbox );
11851 }
11852 }
11853 return true;
11854 }
11855
11856 bool ON_BrepTrim::TransformTrim( const ON_Xform& xform )
11857 {
11858
11859 DestroyCurveTree();
11860 m_pline.Destroy();
11861
11862 if ( !m_brep )
11863 return false;
11864
11865
11866 if ( !m_brep->StandardizeTrimCurve( m_trim_index ) )
11867 return false;
11868
11869
11870 ON_Curve* c2 = const_cast<ON_Curve*>(TrimCurveOf());
11871 if ( !c2 )
11872 return true;
11873 if ( !c2->Transform(xform) )
11874 return false;
11875
11876
11877 m_pbox = c2->BoundingBox();
11878 m_pbox.m_min.z = 0.0;
11879 m_pbox.m_max.z = 0.0;
11880
11881
11882
11883
11884
11885 double tol0 = xform[0][0]*m_tolerance[0] + xform[0][1]*m_tolerance[1];
11886 double tol1 = xform[1][0]*m_tolerance[0] + xform[1][1]*m_tolerance[1];
11887 m_tolerance[0] = fabs(tol0);
11888 m_tolerance[1] = fabs(tol1);
11889
11890 if ( m_iso != ON_Surface::not_iso )
11891 {
11892 m_iso = ON_Surface::not_iso;
11893 m_brep->SetTrimIsoFlags(*this);
11894 }
11895
11896 return true;
11897 }
11898
11899
11900 void ON_BrepTrim::DestroyRuntimeCache( bool bDelete )
11901 {
11902 ON_CurveProxy::DestroyRuntimeCache(bDelete);
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916 }
11917
11918 void ON_BrepLoop::DestroyRuntimeCache( bool bDelete )
11919 {
11920 ON_Object::DestroyRuntimeCache(bDelete);
11921
11922
11923
11924 }
11925
11926 void ON_BrepFace::DestroyRuntimeCache( bool bDelete )
11927 {
11928 ON_SurfaceProxy::DestroyRuntimeCache(bDelete);
11929
11930
11931
11932
11933
11934
11935
11936 m_bbox.Destroy();
11937 }
11938
11939
11940
11941
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
11975
11976
11977
11978
11979
11980
11981
11982
11983
11984
11985
11986
11987
11988
11989
11990 int ON_BrepLoop::Dimension() const
11991 {
11992 return 2;
11993 }
11994
11995 ON_BOOL32 ON_BrepLoop::GetBBox(
11996 double* boxmin,
11997 double* boxmax,
11998 ON_BOOL32 bGrowBox
11999 ) const
12000 {
12001 bool rc = m_pbox.IsValid();
12002 if (rc)
12003 {
12004 ON_BoundingBox bbox;
12005 if ( bGrowBox )
12006 {
12007 bbox.m_min.x = boxmin[0];
12008 bbox.m_min.y = boxmin[1];
12009 bbox.m_min.z = 0.0;
12010 bbox.m_max.x = boxmax[0];
12011 bbox.m_max.y = boxmax[1];
12012 bbox.m_max.z = 0.0;
12013 bbox.Union(m_pbox);
12014 boxmin[0] = bbox.m_min.x;
12015 boxmin[1] = bbox.m_min.y;
12016 boxmax[0] = bbox.m_max.x;
12017 boxmax[1] = bbox.m_max.y;
12018 }
12019 else
12020 {
12021 boxmin[0] = m_pbox.m_min.x;
12022 boxmin[1] = m_pbox.m_min.y;
12023 boxmax[0] = m_pbox.m_max.x;
12024 boxmax[1] = m_pbox.m_max.y;
12025 }
12026 }
12027 return rc;
12028 }
12029
12030 ON_BOOL32 ON_BrepLoop::Transform( const ON_Xform& )
12031 {
12032 return false;
12033 }
12034
12035 ON_COMPONENT_INDEX ON_BrepVertex::ComponentIndex() const
12036 {
12037 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::brep_vertex,m_vertex_index);
12038 return ci;
12039 }
12040
12041 ON_COMPONENT_INDEX ON_BrepEdge::ComponentIndex() const
12042 {
12043 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::brep_edge,m_edge_index);
12044 return ci;
12045 }
12046
12047 ON_COMPONENT_INDEX ON_BrepFace::ComponentIndex() const
12048 {
12049 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::brep_face,m_face_index);
12050 return ci;
12051 }
12052
12053
12054 ON_COMPONENT_INDEX ON_BrepTrim::ComponentIndex() const
12055 {
12056 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::brep_trim,m_trim_index);
12057 return ci;
12058 }
12059
12060
12061
12062 ON_COMPONENT_INDEX ON_BrepLoop::ComponentIndex() const
12063 {
12064 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::brep_loop,m_loop_index);
12065 return ci;
12066 }
12067