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