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