0024425: Improve usage ergonomics of new dimension presentations
[occt.git] / src / ShapeFix / ShapeFix_Shell.cxx
CommitLineData
b311480e 1// Created on: 1998-08-12
2// Created by: Galina KULIKOVA
3// Copyright (c) 1998-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21// pdn 17.12.98 ie_exhaust-A.stp
22
23#include <ShapeFix_Shell.ixx>
24
25#include <Precision.hxx>
26#include <TopAbs.hxx>
27#include <TopoDS_Iterator.hxx>
28#include <TopoDS_Shape.hxx>
29#include <TopoDS_Face.hxx>
30#include <TopoDS_Edge.hxx>
31#include <TopoDS_Shell.hxx>
32#include <TopoDS.hxx>
33#include <TopExp_Explorer.hxx>
34#include <TopExp.hxx>
35
36#include <TColStd_SequenceOfInteger.hxx>
37#include <TopTools_SequenceOfShape.hxx>
38#include <TopTools_MapOfShape.hxx>
39#include <TopTools_MapIteratorOfMapOfShape.hxx>
40#include <TopTools_IndexedMapOfShape.hxx>
41#include <TopTools_DataMapOfShapeShape.hxx>
42#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
43#include <TopTools_ListOfShape.hxx>
44#include <TopTools_ListIteratorOfListOfShape.hxx>
45
46#include <BRep_Builder.hxx>
47#include <BRep_Tool.hxx>
48
a929ed86 49#include <ShapeAnalysis_Shell.hxx>
7fd59977 50#include <ShapeExtend.hxx>
51#include <ShapeBuild_ReShape.hxx>
52#include <Message_Msg.hxx>
b485ee79 53#include <Message_ProgressSentry.hxx>
7fd59977 54#include <TopTools_DataMapOfShapeInteger.hxx>
55#include <TopTools_DataMapOfShapeInteger.hxx>
56#include <TopTools_DataMapOfShapeInteger.hxx>
57#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
58#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
59#include <TColStd_DataMapOfIntegerListOfInteger.hxx>
60#include <Bnd_Box.hxx>
61#include <BRepBndLib.hxx>
62#include <Bnd_Array1OfBox.hxx>
63#include <TColStd_MapOfInteger.hxx>
64#include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
65#include <TopoDS_Iterator.hxx>
66#include <TopTools_IndexedMapOfShape.hxx>
67#include <TopTools_IndexedDataMapOfShapeShape.hxx>
68
69//=======================================================================
70//function : ShapeFix_Shell
71//purpose :
72//=======================================================================
73
74ShapeFix_Shell::ShapeFix_Shell()
75{
76 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
77 myFixFaceMode = -1;
78 myFixOrientationMode = -1;
79 myFixFace = new ShapeFix_Face;
80 myNbShells =0;
81}
82
83//=======================================================================
84//function : ShapeFix_Shell
85//purpose :
86//=======================================================================
87
88ShapeFix_Shell::ShapeFix_Shell(const TopoDS_Shell& shape)
89{
90 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
91 myFixFaceMode = -1;
92 myFixOrientationMode = -1;
93 myFixFace = new ShapeFix_Face;
94 Init(shape);
95}
96
97//=======================================================================
98//function : Init
99//purpose :
100//=======================================================================
101
102void ShapeFix_Shell::Init(const TopoDS_Shell& shell)
103{
104 myShape = shell;
105 myShell = shell;
106 myNbShells =0;
107}
108
109//=======================================================================
110//function : Perform
111//purpose :
112//=======================================================================
113
b485ee79 114Standard_Boolean ShapeFix_Shell::Perform(const Handle(Message_ProgressIndicator)& theProgress)
7fd59977 115{
116 Standard_Boolean status = Standard_False;
b485ee79
KD
117 if ( Context().IsNull() )
118 SetContext(new ShapeBuild_ReShape);
7fd59977 119 myFixFace->SetContext(Context());
b485ee79
KD
120
121 if ( NeedFix(myFixFaceMode) )
122 {
123 TopoDS_Shape S = Context()->Apply(myShell);
124
125 // Get the number of faces for progress indication
126 Standard_Integer aNbFaces = 0;
127 for ( TopExp_Explorer aFaceExp(S, TopAbs_FACE); aFaceExp.More(); aFaceExp.Next() )
128 ++aNbFaces;
129
130 // Start progress scope (no need to check if progress exists -- it is safe)
131 Message_ProgressSentry aPSentry(theProgress, "Fixing face", 0, aNbFaces, 1);
132
133 for( TopoDS_Iterator iter(S); iter.More() && aPSentry.More(); iter.Next(), aPSentry.Next() )
134 {
7fd59977 135 TopoDS_Shape sh = iter.Value();
136 TopoDS_Face tmpFace = TopoDS::Face(sh);
137 myFixFace->Init(tmpFace);
b485ee79
KD
138 if ( myFixFace->Perform() )
139 {
140 status = Standard_True;
141 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
7fd59977 142 }
143 }
b485ee79
KD
144
145 // Halt algorithm in case of user's abort
146 if ( !aPSentry.More() )
147 return Standard_False;
7fd59977 148 }
149 TopoDS_Shape newsh = Context()->Apply(myShell);
150 if ( NeedFix ( myFixOrientationMode) )
151 FixFaceOrientation(TopoDS::Shell(newsh));
a929ed86 152
153 TopoDS_Shape aNewsh = Context()->Apply (newsh);
154 ShapeAnalysis_Shell aSas;
155 for (TopExp_Explorer aShellExp (aNewsh, TopAbs_SHELL); aShellExp.More(); aShellExp.Next())
156 {
157 TopoDS_Shell aCurShell = TopoDS::Shell (aShellExp.Current());
158 if (aCurShell.Closed())
159 {
160 aSas.LoadShells (aCurShell);
161 aSas.CheckOrientedShells (aCurShell, Standard_True);
162 if (aSas.HasFreeEdges())
163 {
164 aCurShell.Closed (Standard_False);
165 SendWarning (Message_Msg ("FixAdvShell.FixClosedFlag.MSG0"));//Shell has incorrect flag isClosed
166 }
167 aSas.Clear();
168 }
169 }
170
7fd59977 171 if ( status )
172 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
173 if(Status(ShapeExtend_DONE2))
174 status = Standard_True;
175 return status;
176}
177
178//=======================================================================
179// function : GetFreeEdges
180// purpose :
181//=======================================================================
182static Standard_Boolean GetFreeEdges(const TopoDS_Shape& aShape,TopTools_MapOfShape& MapEdges)
183{
184 for(TopExp_Explorer aExpF(aShape,TopAbs_FACE); aExpF.More(); aExpF.Next()) {
185 for(TopExp_Explorer aExpE(aExpF.Current(),TopAbs_EDGE); aExpE.More(); aExpE.Next()) {
186 TopoDS_Edge edge = TopoDS::Edge(aExpE.Current());
187 if(!MapEdges.Contains(edge))
188 MapEdges.Add(edge);
189 else MapEdges.Remove(edge);
190 }
191 }
192 return (MapEdges.Extent());
193}
194//=======================================================================
195// function : GetShells
196// purpose : If mode isMultiConnex = Standard_True gets max possible shell for
197// exception of multiconnexity parts.
198// Else if this mode is equal to Standard_False maximum possible
199// shell will be created without taking account of multiconnexity.
200// In this function map face - shell and sequence of mebius faces is formed.
201//=======================================================================
202static Standard_Boolean GetShells(TopTools_SequenceOfShape& Lface,
203 const TopTools_MapOfShape& aMapMultiConnectEdges,
204 TopTools_SequenceOfShape& aSeqShells,
205 TopTools_DataMapOfShapeShape& aMapFaceShells,
206 TopTools_SequenceOfShape& ErrFaces)
207{
208 Standard_Boolean done = Standard_False;
209 if(!Lface.Length()) return Standard_False;
210 TopoDS_Shell nshell;
211 TopTools_MapOfShape dire, reve;
212 BRep_Builder B;
213 B.MakeShell(nshell);
214 Standard_Boolean isMultiConnex = !aMapMultiConnectEdges.IsEmpty();
215 Standard_Integer i=1, j=1;
216 TopTools_SequenceOfShape aSeqUnconnectFaces;
217 for( ; i<=Lface.Length(); i++) {
218 TopTools_MapOfShape dtemp, rtemp;
219 Standard_Integer nbbe=0, nbe = 0;
220 TopoDS_Face F1 = TopoDS::Face(Lface.Value(i));
221 for(TopExp_Explorer expe(F1, TopAbs_EDGE); expe.More(); expe.Next()) {
222 TopoDS_Edge edge = TopoDS::Edge(expe.Current());
223
224 // if multiconnexity mode is equal to Standard_True faces contains
225 // the same multiconnexity edges are not added to one shell.
226 if(isMultiConnex && aMapMultiConnectEdges.Contains(edge))
227 continue;
228
229 if((edge.Orientation() == TopAbs_FORWARD && dire.Contains(edge))
230 || (edge.Orientation() == TopAbs_REVERSED && reve.Contains(edge)))
231 nbbe++;
232 else if((edge.Orientation() == TopAbs_FORWARD && reve.Contains(edge))
233 || (edge.Orientation() == TopAbs_REVERSED && dire.Contains(edge)))
234 nbe++;
235
236 if(dire.Contains(edge)) dire.Remove(edge);
237 else
238 if(reve.Contains(edge)) reve.Remove(edge);
239 else {
240 if(edge.Orientation() == TopAbs_FORWARD) dtemp.Add(edge);
241 if(edge.Orientation() == TopAbs_REVERSED) rtemp.Add(edge);
242 }
243 }
244 if(!nbbe && !nbe && dtemp.IsEmpty() && rtemp.IsEmpty())
245 continue;
246
247 // if face can not be added to shell it added to sequence of error faces.
248
249 if( nbe != 0 && nbbe != 0) {
250 ErrFaces.Append(F1);
251 Lface.Remove(i);
252 j++;
253 continue;
254 }
255
256 // Addition of face to shell. In the dependance of orientation faces in the shell
257 // added face can be reversed.
258
259 if((nbe != 0 || nbbe != 0) || j == 1) {
260 if(nbbe != 0) {
261 F1.Reverse();
262 for(TopTools_MapIteratorOfMapOfShape ite(dtemp); ite.More(); ite.Next())
263 reve.Add(ite.Key());
264 for(TopTools_MapIteratorOfMapOfShape ite1(rtemp); ite1.More(); ite1.Next())
265 dire.Add(ite1.Key());
266 done = Standard_True;
267 }
268 else {
269 for(TopTools_MapIteratorOfMapOfShape ite(dtemp); ite.More(); ite.Next())
270 dire.Add(ite.Key());
271 for(TopTools_MapIteratorOfMapOfShape ite1(rtemp); ite1.More(); ite1.Next())
272 reve.Add(ite1.Key());
273 }
274 j++;
275 B.Add(nshell,F1);
276 aMapFaceShells.Bind(F1,nshell);
277 Lface.Remove(i);
278
279 // if closed shell is obtained it adds to sequence of shells and new shell begin to construct.
280 if(isMultiConnex && BRep_Tool::IsClosed(nshell)) {
281 aSeqShells.Append(nshell);
282 TopoDS_Shell nshellnext;
283 B.MakeShell(nshellnext);
284 nshell = nshellnext;
285 j=1;
286 }
287
288 i=0;
289 }
290 //if shell contains of one face. This face is added to sequence of faces.
291 // This shell is removed.
292 if(Lface.Length() && i == Lface.Length() && j <=2) {
293 TopoDS_Iterator aItf(nshell,Standard_False);
294 if(aItf.More()) {
295 aSeqUnconnectFaces.Append(aItf.Value());
296 aMapFaceShells.UnBind(aItf.Value());
297 }
298 TopoDS_Shell nshellnext;
299 B.MakeShell(nshellnext);
300 nshell = nshellnext;
301 i=0;
302 j=1;
303 }
304 }
305 Standard_Boolean isContains = Standard_False;
306 for(Standard_Integer k =1 ; k <= aSeqShells.Length() && !isContains; k++)
307 isContains = nshell.IsSame(aSeqShells.Value(k));
308 if(!isContains) {
309 Standard_Integer numFace =0;
310 TopoDS_Shape aFace;
311 for(TopoDS_Iterator aItf(nshell,Standard_False) ; aItf.More(); aItf.Next()) {
312 aFace = aItf.Value();
313 numFace++;
314 }
315 if(numFace >1)
316 aSeqShells.Append(nshell);
317 else if(numFace == 1) {
318 if(aMapFaceShells.IsBound(aFace))
319 aMapFaceShells.UnBind(aFace);
320 Lface.Append(aFace);
321 }
322 }
323
324 //Sequence of faces Lface contains faces which can not be added to obtained shells.
325 for(Standard_Integer j1 =1; j1 <= aSeqUnconnectFaces.Length(); j1++) {
326 Lface.Append(aSeqUnconnectFaces);
327 }
328
329 return done;
330}
331//=======================================================================
332// function : AddMultiConexityFaces
333// purpose : In this function faces have only of multiconnexity boundary
334// are added to shells having free boundary contains the same
335// multiconnexity edges as faces.
336//=======================================================================
337static Standard_Boolean AddMultiConexityFaces(TopTools_SequenceOfShape& Lface,
338 const TopTools_MapOfShape& aMapMultiConnectEdges,
339 TopTools_SequenceOfShape& SeqShells,
340 const TopTools_DataMapOfShapeShape& aMapFaceShells,
341 const TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces,
342 TopTools_SequenceOfShape& ErrFaces,
343 const Standard_Boolean NonManifold)
344{
345 Standard_Boolean done = Standard_False;
346// BRep_Builder aB;
347 TopTools_SequenceOfShape llPosibleShells;
348 TopTools_SequenceOfShape AddShapes;
349 for(Standard_Integer i1 = 1 ; i1<=Lface.Length();i1++ ) {
350
351 TopoDS_Shape aShape = Lface.Value(i1);
352
353 Standard_Integer aNbMultEdges =0;
354
355 //Finds faces having only multiconnexity boundary.
356 for(TopoDS_Iterator aItWires(aShape,Standard_False); aItWires.More(); aItWires.Next()) {
357 Standard_Integer aNbEdges =0;
358 for(TopoDS_Iterator aItEdges(aItWires.Value(),Standard_False); aItEdges.More(); aItEdges.Next(),aNbEdges++) {
359 TopoDS_Shape edge = aItEdges.Value();
360 if(!aMapMultiConnectEdges.Contains(edge)) continue;
361 aNbMultEdges++;
362 }
363 if(!aNbMultEdges) continue;
364
365 if(aNbMultEdges == aNbEdges)
366 AddShapes.Append(aShape);
367 else llPosibleShells.Append(aShape);
368 }
369 }
370
371 // Attemp to create shell from unconnected which have not only multiconnexity boundary.
372 TopTools_SequenceOfShape aTmpShells;
373 if(!llPosibleShells.IsEmpty()) {
374 TopTools_MapOfShape aMap;
375 TopTools_SequenceOfShape aTmp;
376 TopTools_DataMapOfShapeShape aTmpFaceShell;
377 if(GetShells(llPosibleShells,aMap,aTmpShells,aTmpFaceShell,aTmp)) {
378 for(Standard_Integer kk =1; kk <= aTmpShells.Length(); kk++) {
379 TopoDS_Shape aSh = aTmpShells.Value(kk);
380 TopTools_MapOfShape mapEdges;
381 if(GetFreeEdges(aSh,mapEdges)) {
382 Standard_Integer nbedge =0;
383 for(TopTools_MapIteratorOfMapOfShape amapIter(mapEdges);amapIter.More(); amapIter.Next()) {
384 if( aMapMultiConnectEdges.Contains(amapIter.Key()))
385 nbedge++;
386 }
387 if(nbedge && nbedge == mapEdges.Extent())
388 AddShapes.Append(aSh);
389 }
390 }
391 }
392 }
393
394 //Add choosen faces to shells.
395 for(Standard_Integer k1 =1; k1 <= AddShapes.Length(); k1++) {
396 TopTools_DataMapOfShapeInteger MapOtherShells;
397 TopTools_MapOfShape dire,reve;
398 TopoDS_Shape aSh = AddShapes.Value(k1);
399 TopTools_MapOfShape mapEdges;
400 if(!GetFreeEdges(aSh,mapEdges)) continue;
401 TopTools_ListOfShape lfaces;
402
403 //Fill MapOtherShells which will contain shells with orientation in which selected shape aSh will be add.
404
405 for(TopTools_MapIteratorOfMapOfShape amapIter(mapEdges);amapIter.More(); amapIter.Next()) {
406 if(!aMapMultiConnectEdges.Contains(amapIter.Key())) continue;
407 TopoDS_Edge edge = TopoDS::Edge(amapIter.Key());
408 if( edge.Orientation() == TopAbs_FORWARD) dire.Add(edge);
409 else reve.Add(edge);
410 TopTools_ListOfShape lf;
411 lf = aMapEdgeFaces.FindFromKey(edge);
412 lfaces.Append(lf);
413 }
414 for(TopTools_ListIteratorOfListOfShape aItl(lfaces) ; aItl.More(); aItl.Next()) {
415 TopoDS_Shape aF = aItl.Value();
416 if(!aMapFaceShells.IsBound( aF)) continue;
417
418 TopoDS_Shape aOthershell;
419 aOthershell = aMapFaceShells.Find(aF);
420 if(MapOtherShells.IsBound(aOthershell)) continue;
421 if(!NonManifold && BRep_Tool::IsClosed(aOthershell))
422 continue;
423
424 TopTools_MapOfShape mapShellEdges;
425 GetFreeEdges(aOthershell,mapShellEdges);
426 Standard_Boolean isAdd = Standard_True;
427 for(TopTools_MapIteratorOfMapOfShape amapIter1(mapEdges);amapIter1.More() && isAdd ; amapIter1.Next())
428 isAdd = mapShellEdges.Contains(amapIter1.Key());
429
430 if(!isAdd) continue;
431 Standard_Integer nbdir =0, nbrev=0;
432
433 //add only free face whome all edges contains in the shell as open boundary.
434 for(TopTools_MapIteratorOfMapOfShape aIte( mapShellEdges);aIte.More() ;aIte.Next()) {
435 TopoDS_Edge edgeS = TopoDS::Edge(aIte.Key());
436 if(!aMapMultiConnectEdges.Contains(edgeS)) continue;
437 if( (edgeS.Orientation() == TopAbs_FORWARD && dire.Contains(edgeS)) || (edgeS.Orientation() == TopAbs_REVERSED && reve.Contains(edgeS))) nbrev++;
438 else if((edgeS.Orientation() == TopAbs_FORWARD && reve.Contains(edgeS))
439 || (edgeS.Orientation() == TopAbs_REVERSED && dire.Contains(edgeS))) nbdir++;
440 }
441 if(nbdir && nbrev) {
442 ErrFaces.Append(aSh);
443 continue;
444 }
445 if(nbdir || nbrev) {
446 Standard_Integer isReverse =(nbrev ? 1: 0);
447 MapOtherShells.Bind(aOthershell,isReverse);
448 }
449
450 }
451 if(MapOtherShells.IsEmpty()) {
452// i1++;
453 continue;
454 }
455
456 //Adds face to open shells containg the same multishared edges.
457 //For nonmanifold mode creation ine shell from face and shells containing the same multishared edges.
458 // If one face can be added to a few shells (case of compsolid) face will be added to each shell.
459 done = Standard_True;
460 Standard_Integer FirstRev = 0,FirstInd =0;
461 Standard_Integer ind =0;
462 for(Standard_Integer l =1; l <= SeqShells.Length(); l++) {
463 if(!MapOtherShells.IsBound(SeqShells.Value(l))) continue;
464 ind++;
465 Standard_Integer isRev = MapOtherShells.Find(SeqShells.Value(l));
466 TopoDS_Shape anewShape = (isRev ? aSh.Reversed() :aSh);
467
468 BRep_Builder aB1;
469 TopoDS_Shape aShell = SeqShells.Value(l);
470 if(ind ==1 || !NonManifold) {
471 if(ind ==1) {
472 FirstRev = isRev;
473 FirstInd = l;
474 }
475 for(TopExp_Explorer aE(anewShape,TopAbs_FACE); aE.More(); aE.Next())
476 aB1.Add(aShell,aE.Current());
477 SeqShells.ChangeValue(l) = aShell;
478 }
479 else if(NonManifold) {
480 Standard_Boolean isReversed = !((!(isRev) && !FirstRev) || ((isRev) && FirstRev));
481 aShell = SeqShells.Value(FirstInd);
482 for(TopoDS_Iterator aItF(SeqShells.Value(l),Standard_False); aItF.More(); aItF.Next()) {
483 TopoDS_Shape nF = ( isReversed ? aItF.Value().Reversed() : aItF.Value());
484 aB1.Add(aShell,nF);
485 }
486 SeqShells.ChangeValue(FirstInd) = aShell;
487 SeqShells.Remove(l--);
488 }
489 }
490
491 dire.Clear();
492 reve.Clear();
493 for(TopExp_Explorer aEt(aSh,TopAbs_FACE); aEt.More(); aEt.Next()) {
494 for(Standard_Integer kk =1 ; kk <= Lface.Length(); kk++) {
495 if(aEt.Current().IsSame(Lface.Value(kk)))
496 Lface.Remove(kk--);
497 }
498 }
499 }
500 return done;
501}
502
503//=======================================================================
504// function : BoxIn
505// purpose : Check if one face contains inside other.
506//=======================================================================
507static Standard_Integer BoxIn(const Bnd_Box& theBox1,const Bnd_Box& theBox2)
508{
509 Standard_Integer aNumIn = 0;
510 Standard_Real aXmin1,aYmin1,aXmax1,aYmax1,aXmin2,aYmin2,aXmax2,aYmax2,aZmin1,aZmax1,aZmin2,aZmax2;
511 theBox1.Get(aXmin1,aYmin1,aZmin1,aXmax1,aYmax1,aZmax1);
512 theBox2.Get(aXmin2,aYmin2,aZmin2,aXmax2,aYmax2,aZmax2);
513 if(aXmin1 == aXmin2 && aXmax1 == aXmax2 && aYmin1 == aYmin2 && aYmax1 == aYmax2 &&
514 aZmin1 == aZmin2 && aZmax1 == aZmax2)
515 aNumIn = 0;
516 else if( aXmin1 >= aXmin2 && aXmax1 <= aXmax2 && aYmin1 >= aYmin2 && aYmax1 <= aYmax2 &&
517 aZmin1 >= aZmin2 && aZmax1 <= aZmax2)
518 aNumIn = 1;
519 else if( aXmin1 <= aXmin2 && aXmax1 >= aXmax2 && aYmin1 <= aYmin2 && aYmax1 >= aYmax2 && aZmin1 <= aZmin2 && aZmax1 >= aZmax2)
520 aNumIn = 2;
521 return aNumIn;
522}
523//=======================================================================
524// function : GetClosedShells
525// purpose : Check if one shell is a part from other shell.
526// For case of compsolid when afew shells are created from
527// the same set of faces.
528//=======================================================================
529static void GetClosedShells(TopTools_SequenceOfShape& Shells, TopTools_SequenceOfShape& aRemainShells)
530{
531 Bnd_Array1OfBox aBoxes(1,Shells.Length());
532 for(Standard_Integer i =1; i <= Shells.Length(); i++) {
533 Bnd_Box Box;
534 BRepBndLib::AddClose(Shells.Value(i),Box);
535 aBoxes.SetValue(i,Box);
536 }
537 TColStd_MapOfInteger aMapNum;
538 for(Standard_Integer j = 1; j <= aBoxes.Length(); j++) {
539 for(Standard_Integer k = j+1; k <= aBoxes.Length(); k++) {
540 Standard_Integer NumIn = BoxIn(aBoxes.Value(j),aBoxes.Value(k));
541 switch(NumIn) {
542 case 1:aMapNum.Add(k); break;
543 case 2: aMapNum.Add(j); break;
544 default : break;
545 }
546 }
547 }
548 for(Standard_Integer i1 =1; i1 <= Shells.Length(); i1++) {
549 if(!aMapNum.Contains(i1))
550 aRemainShells.Append(Shells.Value(i1));
551 }
552
553}
554//=======================================================================
555// function : GlueClosedCandidate
556// purpose :Attemt firstly to create closed shells from sequence of open shells.
557//=======================================================================
558static void GlueClosedCandidate(TopTools_SequenceOfShape& OpenShells,
559 const TopTools_MapOfShape& aMapMultiConnectEdges,
560 TopTools_SequenceOfShape& aSeqNewShells)
561
562{
563 // Creating new shells if some open shells contain the same free boundary.
564 for(Standard_Integer i = 1 ; i < OpenShells.Length();i++ ) {
565 TopoDS_Shape aShell = OpenShells.Value(i);
566 TopTools_MapOfShape mapEdges1;
567 TopTools_MapOfShape dire,reve;
568 if(!GetFreeEdges(aShell,mapEdges1)) continue;
569
570 for(TopTools_MapIteratorOfMapOfShape aIte( mapEdges1);aIte.More() ;aIte.Next()) {
571 TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
572 if(!aMapMultiConnectEdges.Contains(edge1)) break;
573 if(edge1.Orientation() == TopAbs_FORWARD) dire.Add(edge1);
574 else if(edge1.Orientation() == TopAbs_REVERSED) reve.Add(edge1);
575 }
576 if(mapEdges1.Extent() >(dire.Extent() + reve.Extent())) continue;
577
578 //Filling map MapOtherShells which contains candidate to creation of closed shell
579 // with aShell.
580
581 TopTools_DataMapOfShapeInteger MapOtherShells;
582
583 for(Standard_Integer j = i+1 ; j <= OpenShells.Length();j++ ) {
584 Standard_Boolean isAddShell = Standard_True;
585 Standard_Boolean isReversed = Standard_False;
586 Standard_Integer nbedge =0;
587 TopTools_MapOfShape mapEdges2;
588 TopoDS_Shape aShell2 = OpenShells.Value(j);
589 if(!GetFreeEdges(aShell2,mapEdges2)) continue;
590 for(TopTools_MapIteratorOfMapOfShape aIte2( mapEdges2);aIte2.More() && isAddShell;aIte2.Next()) {
591 TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
592 if(!aMapMultiConnectEdges.Contains(edge2)) {
593 isAddShell = Standard_False;
594 break;
595 //continue;
596 }
597 isAddShell = (dire.Contains(edge2) || reve.Contains(edge2));
598 if((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
599 || (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
600 isReversed = Standard_True;
601 nbedge++;
602 }
603
604 if(!isAddShell) continue;
605 MapOtherShells.Bind(OpenShells.Value(j),isReversed);
606 }
607 if(!MapOtherShells.Extent()) continue;
608
609
610 if(MapOtherShells.Extent() >1) {
611
612 // Case of compsolid when more than two shells have the same free boundary.
613 TopTools_SequenceOfShape aSeqCandidate;
614 aSeqCandidate.Append(OpenShells.Value(i));
615
616 for(TopTools_DataMapIteratorOfDataMapOfShapeInteger aIt(MapOtherShells); aIt.More(); aIt.Next())
617 aSeqCandidate.Append(aIt.Key());
618
619 //Creation all possibly shells from choosen candidate.And
620 // addition of them to temporary sequence.
621
622 TopTools_SequenceOfShape aTmpSeq;
623 for(Standard_Integer k =1; k <= aSeqCandidate.Length(); k++) {
624
625 for(Standard_Integer l = k+1; l <= aSeqCandidate.Length(); l++) {
626 TopoDS_Shell aNewSh;
627 BRep_Builder aB;
628 aB.MakeShell(aNewSh);
629 for(TopoDS_Iterator aIt1(aSeqCandidate.Value(k),Standard_False); aIt1.More(); aIt1.Next())
630 aB.Add(aNewSh,aIt1.Value());
631 Standard_Integer isRev = MapOtherShells.Find(aSeqCandidate.Value(l));
632 if(k !=1) {
633 isRev = ((isRev == MapOtherShells.Find(aSeqCandidate.Value(k))) ? 1 : 0);
634 }
635 for(TopExp_Explorer aExp(aSeqCandidate.Value(l),TopAbs_FACE); aExp.More(); aExp.Next()) {
636 TopoDS_Shape aFace = (isRev ? aExp.Current().Reversed(): aExp.Current());
637 aB.Add(aNewSh,aFace);
638 }
639 aTmpSeq.Append(aNewSh);
640 }
641 }
642
643 //Choice from temporary sequence shells contains different set of faces (case of compsolid)
644 TopTools_SequenceOfShape aRemainShells;
645 GetClosedShells(aTmpSeq,aRemainShells);
646 aSeqNewShells.Append(aRemainShells);
647
648 for(Standard_Integer j1 = i+1 ; j1 <= OpenShells.Length();j1++ ) {
649 if(!MapOtherShells.IsBound(OpenShells.Value(j1))) continue;
650 OpenShells.Remove(j1--);
651 }
652
653 }
654 else {
655 BRep_Builder aB;
656 TopoDS_Shape aNewShell = aShell;
657 TopoDS_Shape addShell;
658 Standard_Boolean isReversed = Standard_False;
659 for(Standard_Integer j1 = i+1 ; j1 <= OpenShells.Length();j1++ ) {
660 if(!MapOtherShells.IsBound(OpenShells.Value(j1))) continue;
661 addShell = OpenShells.Value(j1);
662 isReversed = MapOtherShells.Find(addShell);
663 OpenShells.Remove(j1);
664 break;
665 }
666
667 for(TopExp_Explorer aExpF(addShell,TopAbs_FACE); aExpF.More(); aExpF.Next()) {
668 TopoDS_Shape aFace = aExpF.Current();
669 if(isReversed)
670 aFace.Reverse();
671 aB.Add(aNewShell,aFace);
672 }
673 aSeqNewShells.Append(aNewShell);
674 }
675
676 //OpenShells.ChangeValue(i) = aShell;
677 OpenShells.Remove(i--);
678 }
679}
680//=======================================================================
681// function : CreateNonManifoldShells
682// purpose : Attempt to create max possible shells from open shells.
683//=======================================================================
684
685static void CreateNonManifoldShells(TopTools_SequenceOfShape& SeqShells,
686 const TopTools_MapOfShape& aMapMultiConnectEdges)
687{
688 TopTools_IndexedDataMapOfShapeListOfShape aMap;
689 for(Standard_Integer i =1 ; i <= SeqShells.Length(); i++) {
690 TopoDS_Shape aShell = SeqShells.Value(i);
691 TopTools_IndexedMapOfShape medeg;
692 TopExp::MapShapes(aShell,TopAbs_EDGE,medeg);
693 for(TopTools_MapIteratorOfMapOfShape mit(aMapMultiConnectEdges); mit.More(); mit.Next()) {
694 //for(TopExp_Explorer aExp(aShell,TopAbs_EDGE); aExp.More(); aExp.Next(),nbe++) {
695 //TopoDS_Shape ae = aExp.Current();
696 TopoDS_Shape ae =mit.Key();
697 //if( aMapMultiConnectEdges.Contains(aExp.Current())) {
698 if(medeg.Contains(ae)) {
699 if(aMap.Contains(ae))
700 aMap.ChangeFromKey(ae).Append(aShell);
701 else {
702 TopTools_ListOfShape al;
703 al.Append(aShell);
704 aMap.Add(ae,al);
705 }
706 }
707 }
708 }
709 TopTools_IndexedDataMapOfShapeShape aMapShells;
710 for(Standard_Integer j =1; j <= aMap.Extent(); j++) {
711 const TopTools_ListOfShape& LShells = aMap.FindFromIndex(j);
712 TopoDS_Shell aNewShell;
713 BRep_Builder aB;
714 aB.MakeShell(aNewShell);
715 TopTools_MapOfShape mapmerge;
716 Standard_Boolean ismerged = Standard_False;
717 Standard_Integer num = 1;
718 for(TopTools_ListIteratorOfListOfShape alit(LShells); alit.More();alit.Next(),num++) {
719 if(!aMapShells.Contains(alit.Value())) {
720 for(TopExp_Explorer aEf(alit.Value(),TopAbs_FACE); aEf.More(); aEf.Next()) {
721 aB.Add(aNewShell,aEf.Current());
722 }
723 ismerged = Standard_True;
724 mapmerge.Add(alit.Value());
725 }
726 else if(ismerged) {
727 TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
728 while(aMapShells.Contains(arshell)){
729 TopoDS_Shape ss = aMapShells.FindFromKey(arshell);
730 if(ss.IsSame(arshell)) break;
731 arshell = ss;
732 }
733
734 if(!mapmerge.Contains(arshell)) {
735 for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next()) {
736 aB.Add(aNewShell,aEf.Current());
737 }
738 mapmerge.Add(arshell);
739 }
740 }
741 else {
742 TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
743 while(aMapShells.Contains(arshell)) {
744 TopoDS_Shape ss = aMapShells.FindFromKey(arshell);
745 if(ss.IsSame(arshell)) break;
746 arshell = ss;
747 }
748 if(num == 1) {
749 for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next())
750 aB.Add(aNewShell,aEf.Current());
751
752 mapmerge.Add(arshell);
753 }
754 else if(!mapmerge.Contains(arshell)) {
755 for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next()) {
756 aB.Add(aNewShell,aEf.Current());
757 }
758 mapmerge.Add(arshell);
759 }
760 }
761 }
762 if(mapmerge.Extent() >1 || ismerged) {
763 for(TopTools_MapIteratorOfMapOfShape alit1(mapmerge); alit1.More();alit1.Next()) {
764 TopoDS_Shape oldShell = alit1.Key();
765 //while(aMapShells.Contains(oldShell)) {
766 // TopoDS_Shape ss = aMapShells.FindFromKey(oldShell);
767 // if(ss.IsSame(oldShell)) break;
768 // oldShell = ss;
769 //}
770 aMapShells.Add(oldShell,aNewShell);
771 }
772 }
773 }
774 TopTools_IndexedMapOfShape MapNewShells;
775 for(Standard_Integer nn = 1;nn <= SeqShells.Length(); nn++) {
776 if(aMapShells.Contains(SeqShells.Value(nn))) {
777 TopoDS_Shape aNewShell = aMapShells.FindFromKey(SeqShells.Value(nn));
778 while(aMapShells.Contains(aNewShell)) {
779 TopoDS_Shape ss = aMapShells.FindFromKey(aNewShell);
780 if(ss.IsSame(aNewShell)) break;
781 aNewShell = ss;
782 }
783 MapNewShells.Add(aNewShell);
784
785 SeqShells.Remove(nn--);
786 }
787
788 }
789 for(Standard_Integer ii =1; ii <= MapNewShells.Extent(); ii++)
790 SeqShells.Append(MapNewShells.FindKey(ii));
791}
792//=======================================================================
793// function : CreateClosedShell
794// purpose : Attempt to create max possible shells from open shells.
795//=======================================================================
796
797static void CreateClosedShell(TopTools_SequenceOfShape& OpenShells,
798 const TopTools_MapOfShape& aMapMultiConnectEdges)
799{
800 TopTools_SequenceOfShape aNewShells;
801 //Attemt firstly to create closed shells.
802 GlueClosedCandidate(OpenShells,aMapMultiConnectEdges,aNewShells);
803
804 // Creating new shells if some open shells contain the multishared same edges.
805 for(Standard_Integer i = 1 ; i < OpenShells.Length();i++ ) {
806 Standard_Boolean isAddShell = Standard_False;
807 TopoDS_Shape aShell = OpenShells.Value(i);
808 Standard_Boolean isReversed = Standard_False;
809 for(Standard_Integer j = i+1 ; j <= OpenShells.Length();j++ ) {
810 TopTools_MapOfShape mapEdges1;
811 TopTools_MapOfShape dire,reve;
812 if(!GetFreeEdges(aShell,mapEdges1)) break;
813 for(TopTools_MapIteratorOfMapOfShape aIte( mapEdges1);aIte.More() ;aIte.Next()) {
814 TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
815 if(!aMapMultiConnectEdges.Contains(edge1)) continue;
816 if(edge1.Orientation() == TopAbs_FORWARD) dire.Add(edge1);
817 else if(edge1.Orientation() == TopAbs_REVERSED) reve.Add(edge1);
818 }
819 if(dire.IsEmpty() && reve.IsEmpty()) break;
820 TopTools_MapOfShape mapEdges2;
821 TopoDS_Shape aShell2 = OpenShells.Value(j);
822 if(!GetFreeEdges(aShell2,mapEdges2)) continue;
823 for(TopTools_MapIteratorOfMapOfShape aIte2( mapEdges2);aIte2.More() ;aIte2.Next()) {
824 TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
825 if(!aMapMultiConnectEdges.Contains(edge2)) continue;
826 if(!dire.Contains(edge2) && !reve.Contains(edge2)) continue;
827 isAddShell = Standard_True;
828 if((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
829 || (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
830 isReversed = Standard_True;
831 }
832
833 if(!isAddShell) continue;
834 BRep_Builder aB;
835
836 for(TopExp_Explorer aExpF21(OpenShells.Value(j),TopAbs_FACE); aExpF21.More(); aExpF21.Next()) {
837 TopoDS_Shape aFace = aExpF21.Current();
838 if(isReversed)
839 aFace.Reverse();
840 aB.Add( aShell,aFace);
841 }
842
843 OpenShells.ChangeValue(i) = aShell;
844 OpenShells.Remove(j--);
845 }
846 }
847
848 OpenShells.Append(aNewShells);
849
850}
851
852
853//=======================================================================
854// function : FixFaceOrientation
855// purpose :
856//=======================================================================
857
858Standard_Boolean ShapeFix_Shell::FixFaceOrientation(const TopoDS_Shell& shell,const Standard_Boolean isAccountMultiConex,const Standard_Boolean NonManifold)
859{
860 //myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
861 Standard_Boolean done = Standard_False;
862 TopTools_SequenceOfShape aSeqShells;
863 TopTools_SequenceOfShape aErrFaces; // Compound of faces like to Mebiuce leaf.
864 TopTools_SequenceOfShape Lface;
865 TopTools_DataMapOfShapeShape aMapFaceShells;
866 myShell = shell;
867 myShape = shell;
868 Standard_Integer aNumMultShell =0;
869 for (TopoDS_Iterator iter(shell); iter.More(); iter.Next())
870 Lface.Append(iter.Value());
871 TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
872 TopExp::MapShapesAndAncestors(myShell,TopAbs_EDGE,TopAbs_FACE,aMapEdgeFaces);
873 TopTools_MapOfShape aMapMultiConnectEdges;
c4edd925 874 Standard_Boolean isFreeBoundaries = Standard_False;
875 for(Standard_Integer k = 1; k <= aMapEdgeFaces.Extent(); k++) {
876 Standard_Integer aFaceCount = aMapEdgeFaces.FindFromIndex(k).Extent();
7fd59977 877 //Finds multishared edges
c4edd925 878 if (isAccountMultiConex && aFaceCount > 2)
879 aMapMultiConnectEdges.Add(aMapEdgeFaces.FindKey(k));
880 if (aFaceCount == 1)
881 isFreeBoundaries = Standard_True;
882 }
883 if (BRep_Tool::IsClosed (myShell) == isFreeBoundaries)
884 {
885 myShell.Closed (!isFreeBoundaries);
886 SendWarning (Message_Msg ("FixAdvShell.FixClosedFlag.MSG0"));//Shell has incorrect flag isClosed
7fd59977 887 }
888 Standard_Boolean isGetShells = Standard_True;
889 //Gets possible shells with taking in account of multiconnexity.
890 while(isGetShells && Lface.Length()) {
891 TopTools_SequenceOfShape aTmpSeqShells;
892 if(GetShells(Lface, aMapMultiConnectEdges, aTmpSeqShells,aMapFaceShells,aErrFaces)) {
893 done = Standard_True;
894 }
895 isGetShells = !aTmpSeqShells.IsEmpty();
896 if(isGetShells)
897 aSeqShells.Append(aTmpSeqShells);
898 }
899 if(!done)
900 done = (aSeqShells.Length() >1);
901 Standard_Boolean aIsDone = Standard_False;
902 if(Lface.Length() > 0 && aSeqShells.Length()) {
903 for(Standard_Integer jj =1; jj <= Lface.Length(); jj++) {
904 if(aMapFaceShells.IsBound(Lface.Value(jj)))
905 aMapFaceShells.UnBind(Lface.Value(jj));
906 }
907
908 //Addition of faces having only multiconnexity boundary to shells having holes
909 // containing only the multiconnexity edges
910 aIsDone = AddMultiConexityFaces(Lface,aMapMultiConnectEdges,aSeqShells,aMapFaceShells,
911 aMapEdgeFaces,aErrFaces,NonManifold);
912 }
913 aNumMultShell = aSeqShells.Length();
914 if (!aErrFaces.IsEmpty()) {
915
916 //if Shell contains of Mebius faces one shell will be created from each those face.
917 BRep_Builder B;
918 B.MakeCompound(myErrFaces);
919 TopoDS_Compound aCompShells;
920 B.MakeCompound(aCompShells);
921 for(Standard_Integer n =1; n <= aErrFaces.Length(); n++)
922 B.Add(myErrFaces,aErrFaces.Value(n));
923 if(aNumMultShell) {
924 if(aNumMultShell == 1) {
925 B.Add(aCompShells,aSeqShells.Value(1));
926 for(Standard_Integer n1 =1; n1 <= aErrFaces.Length(); n1++) {
927 TopoDS_Shell aSh;
928 B.MakeShell(aSh);
929 B.Add(aSh,aErrFaces.Value(n1));
930 B.Add(aCompShells,aSh);
931 }
932 myShape = aCompShells;
933 }
934 else {
935 for(Standard_Integer i =1; i <= aSeqShells.Length(); i++)
936 B.Add(aCompShells,aSeqShells.Value(i));
937 for(Standard_Integer n1 =1; n1 <= aErrFaces.Length(); n1++) {
938 TopoDS_Shell aSh;
939 B.MakeShell(aSh);
940 B.Add(aSh,aErrFaces.Value(n1));
941 B.Add(aCompShells,aSh);
942 }
943 myShape = aCompShells;
944 }
945 }
946
947 done = Standard_True;
948 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL);
999d2599 949 SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG20" ) );// Impossible to orient faces in shell, several shells created
7fd59977 950 return Standard_True;
951 }
952 if(aNumMultShell >1) {
953 TopTools_SequenceOfShape OpenShells;
954 for(Standard_Integer i1 =1; i1 <= aSeqShells.Length(); i1++) {
955 TopoDS_Shape aShell = aSeqShells.Value(i1);
956 if(!BRep_Tool::IsClosed(aShell)) {
957 OpenShells.Append(aShell);
958 aSeqShells.Remove(i1--);
959 }
960 }
961 if(OpenShells.Length() >1)
962 //Attempt of creation closed shell from open shells with taking into account multiconnexity.
963 CreateClosedShell(OpenShells,aMapMultiConnectEdges);
964 aSeqShells.Append(OpenShells);
965
966 }
967
968 // In the case if NonManifold is equal to Standard_True one non-manifold shell will be created.
969 //Else compound from shells will be created if length of sequence of shape >1.
970 if(Lface.Length()) {
971
972 for(Standard_Integer i = 1; i <= Lface.Length();i++) {
973 BRep_Builder aB;
974 TopoDS_Shell OneShell;
975 aB.MakeShell(OneShell);
976 aB.Add(OneShell, Lface.Value(i));
977 aSeqShells.Append(OneShell);
978 }
979
980 }
981 if(NonManifold && aSeqShells.Length() >1 ) {
982 CreateNonManifoldShells(aSeqShells,aMapMultiConnectEdges);
983 }
984 if(!done)
985 done = (aSeqShells.Length() >1 || aIsDone);
986 if(aSeqShells.Length() == 1) {
987 myShell = TopoDS::Shell(aSeqShells.Value(1));
988 myShape =myShell;
989 myNbShells =1;
990 }
991 else {
992 BRep_Builder B;
993 TopoDS_Compound aCompShells;
994 B.MakeCompound(aCompShells);
995 for(Standard_Integer i =1; i <= aSeqShells.Length(); i++)
996 B.Add(aCompShells,aSeqShells.Value(i));
997 myShape = aCompShells;
998 myNbShells = aSeqShells.Length();
999 }
1000 if(done) {
1001 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
1002 if(!Context().IsNull())
1003 Context()->Replace(shell, myShape);
999d2599
D
1004 if ( myNbShells == 1 )
1005 SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG0" ) );// Faces were incorrectly oriented in the shell, corrected
7fd59977 1006 else
999d2599 1007 SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG30" ) );// Improperly connected shell split into parts
7fd59977 1008 return Standard_True;
1009 }
1010 else return Standard_False;
1011}
1012
1013//=======================================================================
1014//function : Status
1015//purpose :
1016//=======================================================================
1017
1018Standard_Boolean ShapeFix_Shell::Status(const ShapeExtend_Status status) const
1019{
1020 return ShapeExtend::DecodeStatus (myStatus, status);
1021}
1022
1023//=======================================================================
1024//function : Shell
1025//purpose :
1026//=======================================================================
1027
1028TopoDS_Shell ShapeFix_Shell::Shell()
1029{
1030 return myShell;
1031}
1032//=======================================================================
1033//function : Shell
1034//purpose :
1035//=======================================================================
1036
1037TopoDS_Shape ShapeFix_Shell::Shape()
1038{
1039 return myShape;
1040}
1041
1042//=======================================================================
1043//function : ErrorFaces
1044//purpose :
1045//=======================================================================
1046
1047TopoDS_Compound ShapeFix_Shell::ErrorFaces() const
1048{
1049 return myErrFaces;
1050}
1051
1052//=======================================================================
1053//function : SetMsgRegistrator
1054//purpose :
1055//=======================================================================
1056
1057void ShapeFix_Shell::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg)
1058{
1059 ShapeFix_Root::SetMsgRegistrator ( msgreg );
1060 myFixFace->SetMsgRegistrator ( msgreg );
1061}
1062
1063//=======================================================================
1064//function : SetPrecision
1065//purpose :
1066//=======================================================================
1067
1068void ShapeFix_Shell::SetPrecision (const Standard_Real preci)
1069{
1070 ShapeFix_Root::SetPrecision ( preci );
1071 myFixFace->SetPrecision ( preci );
1072}
1073
1074//=======================================================================
1075//function : SetMinTolerance
1076//purpose :
1077//=======================================================================
1078
1079void ShapeFix_Shell::SetMinTolerance (const Standard_Real mintol)
1080{
1081 ShapeFix_Root::SetMinTolerance ( mintol );
1082 myFixFace->SetMinTolerance ( mintol );
1083}
1084
1085//=======================================================================
1086//function : SetMaxTolerance
1087//purpose :
1088//=======================================================================
1089
1090void ShapeFix_Shell::SetMaxTolerance (const Standard_Real maxtol)
1091{
1092 ShapeFix_Root::SetMaxTolerance ( maxtol );
1093 myFixFace->SetMaxTolerance ( maxtol );
1094}
1095//=======================================================================
1096//function : NbShells
1097//purpose :
1098//=======================================================================
1099
1100Standard_Integer ShapeFix_Shell::NbShells() const
1101{
1102 return myNbShells;
1103}