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