Salome HOME
3769b535c0b20ea932bab03bf841903824a15849
[modules/geom.git] / src / ShHealOper / ShHealOper_RemoveFace.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:      ShHealOper_RemoveFace.cxx
24 // Created:   16.04.04 12:12:38
25 // Author:    Galina KULIKOVA
26 //
27 #include <ShHealOper_RemoveFace.hxx>
28 #include <BRepTools_ReShape.hxx>
29 #include <TopoDS_Shape.hxx>
30 #include <TopAbs_ShapeEnum.hxx>
31 #include <TopExp_Explorer.hxx>
32 #include <TopoDS_Compound.hxx>
33 #include <TopoDS_Solid.hxx>
34 #include <TopoDS_Shell.hxx>
35 #include <TopoDS_Face.hxx>
36 #include <BRep_Builder.hxx>
37 #include <TopoDS_Iterator.hxx>
38 #include <TopExp.hxx>
39 #include <TopTools_ListOfShape.hxx>
40 #include <BRep_Tool.hxx>
41 #include <Geom_Surface.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <ShapeBuild_Edge.hxx>
44 #include <ShapeFix_Shell.hxx>
45 #include <ShapeFix_Solid.hxx>
46 #include <TopTools_SequenceOfShape.hxx>
47 #include <TopoDS.hxx>
48 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
49 #include <TopTools_ListIteratorOfListOfShape.hxx>
50
51
52 //=======================================================================
53 //function : ShHealOper_RemoveFace()
54 //purpose  : Constructor
55 //=======================================================================
56 ShHealOper_RemoveFace::ShHealOper_RemoveFace () :
57        ShHealOper_Tool()
58 {
59 }
60 //=======================================================================
61 //function : ShHealOper_RemoveFace
62 //purpose  : 
63 //=======================================================================
64
65 ShHealOper_RemoveFace::ShHealOper_RemoveFace ( const TopoDS_Shape& theShape ) 
66        //ShHealOper_Tool(theShape)
67 {
68   Init(theShape);
69 }
70 //=======================================================================
71 //function : Init
72 //purpose  : 
73 //=======================================================================
74
75 void ShHealOper_RemoveFace::Init(const TopoDS_Shape& theShape)
76 {
77   //myDone = Standard_False;
78   //myInitShape = theShape;
79   //myContext->Apply(myInitShape);
80   ShHealOper_Tool::Init(theShape);
81   myMapEdgesFace.Clear();
82   TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,myMapEdgesFace);
83 }
84 //=======================================================================
85 //function : Perform
86 //purpose  : remove all faces from initial shape
87 //=======================================================================
88
89 Standard_Boolean ShHealOper_RemoveFace::Perform()
90 {
91   myDone = Standard_False;
92   myErrorStatus = ShHealOper_NotError;
93   if(myInitShape.IsNull()) {
94     myErrorStatus = ShHealOper_InvalidParameters;
95     return myDone;
96   }
97   TopExp_Explorer aExp(myInitShape,TopAbs_FACE);
98   for( ; aExp.More(); aExp.Next()) {
99     removePCurve(TopoDS::Face(aExp.Current()));
100     myContext->Remove(aExp.Current());
101     myDone = Standard_True;
102   }
103   if(myDone) {
104     TopoDS_Shape aNewShape = myContext->Apply(myInitShape);
105     isReplace(aNewShape,myResultShape);
106     myContext->Replace(aNewShape,myResultShape);
107   }
108   return myDone;
109 }
110 //=======================================================================
111 //function : Perform
112 //purpose  : remove faces specified by sequence of faces from initial shape.
113 //=======================================================================
114
115 Standard_Boolean ShHealOper_RemoveFace::Perform(const TopTools_SequenceOfShape& theRemoveFaces)
116 {
117   myDone = Standard_False;
118   myErrorStatus = ShHealOper_NotError;
119   if(myInitShape.IsNull()) {
120     myErrorStatus = ShHealOper_InvalidParameters;
121     return myDone;
122   }
123   if(theRemoveFaces.IsEmpty())
124     return Standard_False;
125   myMapFaces.Clear();
126   
127   Standard_Integer i=1; 
128   for( ; i <= theRemoveFaces.Length(); i++)
129     myMapFaces.Add(theRemoveFaces.Value(i));
130   
131   myDone = removeFaces(myInitShape,myResultShape);
132   return myDone;
133 }
134
135 //=======================================================================
136 //function : removeFaces
137 //purpose  : 
138 //=======================================================================
139
140 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shape& theShape,
141                                                     TopoDS_Shape& theNewShape)
142 {
143   Standard_Boolean isDone = Standard_False;
144   
145   TopAbs_ShapeEnum aType = theShape.ShapeType();
146   theNewShape = theShape;
147   if(!myMapFaces.Extent())
148     return isDone;
149   if( aType == TopAbs_WIRE || aType == TopAbs_EDGE || aType == TopAbs_VERTEX)
150       return isDone;
151   if(aType == TopAbs_FACE && myMapFaces.Contains(theShape)) {
152     removePCurve(TopoDS::Face(theShape));
153     
154     myContext->Remove(theShape);
155     myMapFaces.Remove(theShape);
156     //theNewShape = TopoDS_Shape();
157     theNewShape.Nullify();
158     isDone = Standard_True;
159   }
160   else if(aType == TopAbs_SHELL) {
161     isDone = removeFaces(TopoDS::Shell(theShape),theNewShape);
162     return isDone;
163   }
164   else if(aType == TopAbs_SOLID) {
165     isDone = removeFaces(TopoDS::Solid(theShape),theNewShape);
166     myContext->Replace(theShape,theNewShape);
167   }
168   else if(aType == TopAbs_COMPSOLID) {
169
170     //in the case of compsolid method for removing faces for solid
171     //will be used.
172
173     TopExp_Explorer aExpShell(theShape,TopAbs_SHELL);
174     TopoDS_Solid aSol;
175     BRep_Builder aB;
176     aB.MakeSolid(aSol);
177     for( ; aExpShell.More(); aExpShell.Next()) {
178       aB.Add(aSol,aExpShell.Current());
179     }
180     TopoDS_Shape aNewShape;
181     isDone =  removeFaces(aSol,aNewShape);
182     if(isDone)
183        myContext->Replace(theShape,theNewShape);
184     
185   }
186   else if(aType == TopAbs_COMPOUND) {
187     //in the case of compounf faces will be removed from each part of compound separately
188
189     TopoDS_Compound aComp;
190     TopoDS_Iterator aItShape(theShape,Standard_False);
191     BRep_Builder aB;
192     aB.MakeCompound(aComp);
193     Standard_Integer nbs =0;
194     for( ; aItShape.More() ; aItShape.Next()) {
195
196       TopoDS_Shape aNShape;
197       if( removeFaces(aItShape.Value(),aNShape)) {
198         isDone = Standard_True;
199         myContext->Replace(aItShape.Value(),aNShape);
200       }
201       if(!aNShape.IsNull()) {
202         aB.Add(aComp,aNShape);
203         nbs++;
204       }
205     }
206     if(isDone) {
207       if(nbs) 
208         theNewShape = aComp;
209       else
210         theNewShape =TopoDS_Shape();
211       myContext->Replace(theShape,theNewShape);
212     }
213    
214   }
215   return isDone;
216 }
217 //=======================================================================
218 //function : removeFaces
219 //purpose  : function for removing faces from solid
220 //=======================================================================
221
222 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Solid& theShape,
223                                                     TopoDS_Shape& theNewShape)
224 {
225   Standard_Boolean isDone = Standard_False;
226   TopoDS_Solid aSol;
227   BRep_Builder aB;
228   aB.MakeSolid(aSol);
229   TopoDS_Compound aComp;
230   aB.MakeCompound(aComp);
231   Standard_Boolean isAddSol = Standard_False, isAddComp = Standard_False;
232
233   //firslty faces will be deleted from each shell.
234   TopoDS_Iterator aItSol(theShape,Standard_False);
235   for( ; aItSol.More(); aItSol.Next()) {
236     TopoDS_Shape aSh = aItSol.Value();
237     TopoDS_Shape aNewShape;
238     if(removeFaces(aSh,aNewShape)) 
239       isDone = Standard_True;
240     
241     if(aNewShape.IsNull())
242       continue;
243     else if(aNewShape.ShapeType() == TopAbs_SHELL ) {
244       aB.Add(aSol,aNewShape);
245       isAddSol = Standard_True;
246     }
247     else {
248       aB.Add(aComp,aNewShape);
249       isAddComp = Standard_True;
250     }
251     
252   }
253   if(isDone) {
254     //for getting correct solids class ShapeFix_Solid will be used.
255     if(isAddSol) {
256       Handle(ShapeFix_Solid) aSfSol = new ShapeFix_Solid(aSol);
257       aSfSol->FixShellMode()= Standard_False;
258       aSfSol->Perform();
259       TopoDS_Shape aresSol = aSfSol->Shape();
260       if(!isAddComp) 
261         theNewShape = aresSol;
262       else 
263         aB.Add(aComp,aresSol);
264     }
265     else if(isAddComp)
266         theNewShape = aComp;
267     else
268       theNewShape.Nullify();
269   }
270   else
271     theNewShape = theShape; 
272   return isDone;
273 }
274 //=======================================================================
275 //function : IsManifold
276 //purpose  : function for definition manifold shell
277 //=======================================================================
278 Standard_Boolean ShHealOper_RemoveFace::isManifold(const TopoDS_Shell& aShell)
279 {
280   Standard_Boolean IsManifold = Standard_True;
281   TopExp_Explorer aExp(aShell,TopAbs_EDGE);
282   for( ; aExp.More() && IsManifold; aExp.Next()) {
283     const TopTools_ListOfShape& als = myMapEdgesFace.FindFromKey(aExp.Current());
284     IsManifold = (als.Extent() <=2 ); 
285   }
286   return IsManifold;
287 }
288
289 //=======================================================================
290 //function : getResultShell
291 //purpose  : function for avoiding empty shall or shell containing one face.
292 //=======================================================================
293 static TopoDS_Shape getResultShell(const TopoDS_Shape& theNewShell)
294 {
295   TopoDS_Shape rs;
296   Standard_Integer NbFacesShell =0;
297   TopoDS_Shape aF;
298   TopoDS_Iterator aI(theNewShell,Standard_False);
299   for(; aI.More(); aI.Next(),NbFacesShell++)
300     aF = aI.Value();
301   if(NbFacesShell >1)
302     rs = theNewShell;
303   else if(!aF.IsNull())
304     rs = aF;
305   return rs;
306 }
307
308 //=======================================================================
309 //function : removeFaces
310 //purpose  : function for removing faces from shell
311 //=======================================================================
312
313 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shell& theShell,
314                                                     TopoDS_Shape& theNewShape)
315 {
316   
317   Standard_Boolean aIsRemove = Standard_False;
318   //TopoDS_Shape aShape = myReShape->Apply(theShape);
319   //removing faces from shell.
320   TopoDS_Iterator aIterFaces(theShell,Standard_False);
321   for(; aIterFaces.More() && myMapFaces.Extent(); aIterFaces.Next()) {
322
323     if(!myMapFaces.Contains(aIterFaces.Value()))
324       continue;
325     TopoDS_Face aFace = TopoDS::Face( aIterFaces.Value());
326     removePCurve(aFace);
327     aIsRemove  = Standard_True;
328     myContext->Remove(aFace);
329     myMapFaces.Remove(aFace);
330   }
331   if(aIsRemove) {
332     TopoDS_Shape aNewShape = myContext->Apply(theShell);
333     //avoiding empty shell and shell containing one face.
334     TopoDS_Shape aresShape = getResultShell(aNewShape);
335     if(aresShape.IsNull()) {
336       myContext->Remove(aNewShape);
337       theNewShape.Nullify();
338     }
339     else if(aresShape.ShapeType() == TopAbs_FACE) {
340       myContext->Replace(aNewShape,aresShape);
341       theNewShape = aresShape;
342     }
343     else if(aresShape.ShapeType() == TopAbs_SHELL) {
344       //obtaining correct shell or compound with help class ShapeFix_Shell.
345       Standard_Boolean isManifShell = isManifold(theShell);
346       Handle(ShapeFix_Shell) aFixShell = new ShapeFix_Shell;
347       aFixShell->FixFaceOrientation(TopoDS::Shell(aresShape),Standard_True,!isManifShell);
348       TopoDS_Shape aFixShape = aFixShell->Shape();
349       TopoDS_Shape areplShape;
350       isReplace(aFixShape,areplShape);
351       myContext->Replace(aNewShape,areplShape);
352       theNewShape = areplShape;
353     }
354   }
355   else theNewShape = theShell;
356   return aIsRemove;
357 }
358 //=======================================================================
359 //function : isReplace
360 //purpose  : method to avoiding empty compounds and shells.
361 //=======================================================================
362
363 Standard_Boolean ShHealOper_RemoveFace::isReplace(const TopoDS_Shape& theShape, 
364                                                   TopoDS_Shape& theNewShape)
365 {
366   
367   Standard_Boolean isChange = Standard_False;
368   TopTools_SequenceOfShape aSeqShapes;
369   if(theShape.ShapeType() == TopAbs_COMPOUND || theShape.ShapeType() == TopAbs_COMPSOLID ||
370      theShape.ShapeType() == TopAbs_SOLID) {
371     TopoDS_Iterator aEs(theShape);
372     for( ; aEs.More(); aEs.Next()) {
373       TopoDS_Shape aNewShell = aEs.Value();
374       if(aNewShell.ShapeType()!= TopAbs_SHELL) {
375         aSeqShapes.Append(aNewShell);
376         continue;
377       }
378       TopoDS_Shape as = getResultShell(TopoDS::Shell(aNewShell));
379       isChange = (as.IsNull() || (as.ShapeType() == TopAbs_FACE));
380       if(!as.IsNull()) {
381         aSeqShapes.Append(as);
382       }
383     }
384   }
385   else if(theShape.ShapeType() == TopAbs_SHELL) {
386     TopoDS_Shape aSh = getResultShell(TopoDS::Shell(theShape));
387     isChange = (aSh.IsNull() || (aSh.ShapeType() == TopAbs_FACE));
388     if(!aSh.IsNull())
389       aSeqShapes.Append(aSh);
390   }
391   else aSeqShapes.Append(theShape);
392
393   if(aSeqShapes.IsEmpty())
394     return Standard_True;
395
396   if(isChange) {
397     if(aSeqShapes.Length() == 1)
398       theNewShape = aSeqShapes.Value(1);
399     else if (aSeqShapes.Length() > 1) {
400       TopoDS_Compound aComp1;
401       BRep_Builder aBB;
402       aBB.MakeCompound(aComp1);
403       Standard_Integer kk =1;
404       for( ; kk <=  aSeqShapes.Length(); kk++)
405         aBB.Add(aComp1,aSeqShapes.Value(kk));
406       if(aSeqShapes.Length())
407         theNewShape = aComp1;
408     }
409   }
410   else
411     theNewShape = theShape;
412   return isChange;
413 }
414 //=======================================================================
415 //function : removePCurve
416 //purpose  : 
417 //=======================================================================
418
419 void ShHealOper_RemoveFace::removePCurve(const TopoDS_Face& theFace)
420 {
421   //removing pcurves belonging removed face.
422   Handle(Geom_Surface) aSurfDel = BRep_Tool::Surface(theFace);
423   for(TopExp_Explorer aExpEdges(theFace,TopAbs_EDGE);  aExpEdges.More();  aExpEdges.Next()) {
424     const TopTools_ListOfShape& alFaces = myMapEdgesFace.FindFromKey(aExpEdges.Current());
425     Standard_Boolean aIsDeleted = Standard_True;
426     
427     //pcurve will be removed if containing this edge faces have different surfaces.
428     TopTools_ListIteratorOfListOfShape aIterOtherFace(alFaces);
429     for(; aIterOtherFace.More() && aIsDeleted ; aIterOtherFace.Next()) {
430       if(aIterOtherFace.Value().IsSame(theFace))
431          continue;
432       TopoDS_Face aFaceOther = TopoDS::Face(aIterOtherFace.Value());
433       Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFaceOther);
434       aIsDeleted = (aSurf != aSurfDel);
435     }
436     
437     TopoDS_Edge aEdge = TopoDS::Edge(myContext->Apply(aExpEdges.Current()));
438     ShapeBuild_Edge aSbe;
439     TopoDS_Edge aNewEdge = aSbe.Copy(aEdge,Standard_False);
440     if(aIsDeleted) {
441       aSbe.RemovePCurve(aNewEdge,aSurfDel);
442       myContext->Replace(aEdge,aNewEdge);
443       
444     }
445     
446   }
447 }
448