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