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