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