Back to index

salome-geom  6.5.0
ShHealOper_RemoveFace.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File:      ShHealOper_RemoveFace.cxx
00024 // Created:   16.04.04 12:12:38
00025 // Author:    Galina KULIKOVA
00026 //
00027 #include <ShHealOper_RemoveFace.hxx>
00028 #include <BRepTools_ReShape.hxx>
00029 #include <TopoDS_Shape.hxx>
00030 #include <TopAbs_ShapeEnum.hxx>
00031 #include <TopExp_Explorer.hxx>
00032 #include <TopoDS_Compound.hxx>
00033 #include <TopoDS_Solid.hxx>
00034 #include <TopoDS_Shell.hxx>
00035 #include <TopoDS_Face.hxx>
00036 #include <BRep_Builder.hxx>
00037 #include <TopoDS_Iterator.hxx>
00038 #include <TopExp.hxx>
00039 #include <TopTools_ListOfShape.hxx>
00040 #include <BRep_Tool.hxx>
00041 #include <Geom_Surface.hxx>
00042 #include <TopoDS_Edge.hxx>
00043 #include <ShapeBuild_Edge.hxx>
00044 #include <ShapeFix_Shell.hxx>
00045 #include <ShapeFix_Solid.hxx>
00046 #include <TopTools_SequenceOfShape.hxx>
00047 #include <TopoDS.hxx>
00048 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
00049 #include <TopTools_ListIteratorOfListOfShape.hxx>
00050 
00051 
00052 //=======================================================================
00053 //function : ShHealOper_RemoveFace()
00054 //purpose  : Constructor
00055 //=======================================================================
00056 ShHealOper_RemoveFace::ShHealOper_RemoveFace () :
00057        ShHealOper_Tool()
00058 {
00059 }
00060 //=======================================================================
00061 //function : ShHealOper_RemoveFace
00062 //purpose  : 
00063 //=======================================================================
00064 
00065 ShHealOper_RemoveFace::ShHealOper_RemoveFace ( const TopoDS_Shape& theShape ) 
00066        //ShHealOper_Tool(theShape)
00067 {
00068   Init(theShape);
00069 }
00070 //=======================================================================
00071 //function : Init
00072 //purpose  : 
00073 //=======================================================================
00074 
00075 void ShHealOper_RemoveFace::Init(const TopoDS_Shape& theShape)
00076 {
00077   //myDone = Standard_False;
00078   //myInitShape = theShape;
00079   //myContext->Apply(myInitShape);
00080   ShHealOper_Tool::Init(theShape);
00081   myMapEdgesFace.Clear();
00082   TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,myMapEdgesFace);
00083 }
00084 //=======================================================================
00085 //function : Perform
00086 //purpose  : remove all faces from initial shape
00087 //=======================================================================
00088 
00089 Standard_Boolean ShHealOper_RemoveFace::Perform()
00090 {
00091   myDone = Standard_False;
00092   myErrorStatus = ShHealOper_NotError;
00093   if(myInitShape.IsNull()) {
00094     myErrorStatus = ShHealOper_InvalidParameters;
00095     return myDone;
00096   }
00097   TopExp_Explorer aExp(myInitShape,TopAbs_FACE);
00098   for( ; aExp.More(); aExp.Next()) {
00099     removePCurve(TopoDS::Face(aExp.Current()));
00100     myContext->Remove(aExp.Current());
00101     myDone = Standard_True;
00102   }
00103   if(myDone) {
00104     TopoDS_Shape aNewShape = myContext->Apply(myInitShape);
00105     isReplace(aNewShape,myResultShape);
00106     myContext->Replace(aNewShape,myResultShape);
00107   }
00108   return myDone;
00109 }
00110 //=======================================================================
00111 //function : Perform
00112 //purpose  : remove faces specified by sequence of faces from initial shape.
00113 //=======================================================================
00114 
00115 Standard_Boolean ShHealOper_RemoveFace::Perform(const TopTools_SequenceOfShape& theRemoveFaces)
00116 {
00117   myDone = Standard_False;
00118   myErrorStatus = ShHealOper_NotError;
00119   if(myInitShape.IsNull()) {
00120     myErrorStatus = ShHealOper_InvalidParameters;
00121     return myDone;
00122   }
00123   if(theRemoveFaces.IsEmpty())
00124     return Standard_False;
00125   myMapFaces.Clear();
00126   
00127   Standard_Integer i=1; 
00128   for( ; i <= theRemoveFaces.Length(); i++)
00129     myMapFaces.Add(theRemoveFaces.Value(i));
00130   
00131   myDone = removeFaces(myInitShape,myResultShape);
00132   return myDone;
00133 }
00134 
00135 //=======================================================================
00136 //function : removeFaces
00137 //purpose  : 
00138 //=======================================================================
00139 
00140 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shape& theShape,
00141                                                     TopoDS_Shape& theNewShape)
00142 {
00143   Standard_Boolean isDone = Standard_False;
00144   
00145   TopAbs_ShapeEnum aType = theShape.ShapeType();
00146   theNewShape = theShape;
00147   if(!myMapFaces.Extent())
00148     return isDone;
00149   if( aType == TopAbs_WIRE || aType == TopAbs_EDGE || aType == TopAbs_VERTEX)
00150       return isDone;
00151   if(aType == TopAbs_FACE && myMapFaces.Contains(theShape)) {
00152     removePCurve(TopoDS::Face(theShape));
00153     
00154     myContext->Remove(theShape);
00155     myMapFaces.Remove(theShape);
00156     //theNewShape = TopoDS_Shape();
00157     theNewShape.Nullify();
00158     isDone = Standard_True;
00159   }
00160   else if(aType == TopAbs_SHELL) {
00161     isDone = removeFaces(TopoDS::Shell(theShape),theNewShape);
00162     return isDone;
00163   }
00164   else if(aType == TopAbs_SOLID) {
00165     isDone = removeFaces(TopoDS::Solid(theShape),theNewShape);
00166     myContext->Replace(theShape,theNewShape);
00167   }
00168   else if(aType == TopAbs_COMPSOLID) {
00169 
00170     //in the case of compsolid method for removing faces for solid
00171     //will be used.
00172 
00173     TopExp_Explorer aExpShell(theShape,TopAbs_SHELL);
00174     TopoDS_Solid aSol;
00175     BRep_Builder aB;
00176     aB.MakeSolid(aSol);
00177     for( ; aExpShell.More(); aExpShell.Next()) {
00178       aB.Add(aSol,aExpShell.Current());
00179     }
00180     TopoDS_Shape aNewShape;
00181     isDone =  removeFaces(aSol,aNewShape);
00182     if(isDone)
00183        myContext->Replace(theShape,theNewShape);
00184     
00185   }
00186   else if(aType == TopAbs_COMPOUND) {
00187     //in the case of compounf faces will be removed from each part of compound separately
00188 
00189     TopoDS_Compound aComp;
00190     TopoDS_Iterator aItShape(theShape,Standard_False);
00191     BRep_Builder aB;
00192     aB.MakeCompound(aComp);
00193     Standard_Integer nbs =0;
00194     for( ; aItShape.More() ; aItShape.Next()) {
00195 
00196       TopoDS_Shape aNShape;
00197       if( removeFaces(aItShape.Value(),aNShape)) {
00198         isDone = Standard_True;
00199         myContext->Replace(aItShape.Value(),aNShape);
00200       }
00201       if(!aNShape.IsNull()) {
00202         aB.Add(aComp,aNShape);
00203         nbs++;
00204       }
00205     }
00206     if(isDone) {
00207       if(nbs) 
00208         theNewShape = aComp;
00209       else
00210         theNewShape =TopoDS_Shape();
00211       myContext->Replace(theShape,theNewShape);
00212     }
00213    
00214   }
00215   return isDone;
00216 }
00217 //=======================================================================
00218 //function : removeFaces
00219 //purpose  : function for removing faces from solid
00220 //=======================================================================
00221 
00222 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Solid& theShape,
00223                                                     TopoDS_Shape& theNewShape)
00224 {
00225   Standard_Boolean isDone = Standard_False;
00226   TopoDS_Solid aSol;
00227   BRep_Builder aB;
00228   aB.MakeSolid(aSol);
00229   TopoDS_Compound aComp;
00230   aB.MakeCompound(aComp);
00231   Standard_Boolean isAddSol = Standard_False, isAddComp = Standard_False;
00232 
00233   //firslty faces will be deleted from each shell.
00234   TopoDS_Iterator aItSol(theShape,Standard_False);
00235   for( ; aItSol.More(); aItSol.Next()) {
00236     TopoDS_Shape aSh = aItSol.Value();
00237     TopoDS_Shape aNewShape;
00238     if(removeFaces(aSh,aNewShape)) 
00239       isDone = Standard_True;
00240     
00241     if(aNewShape.IsNull())
00242       continue;
00243     else if(aNewShape.ShapeType() == TopAbs_SHELL ) {
00244       aB.Add(aSol,aNewShape);
00245       isAddSol = Standard_True;
00246     }
00247     else {
00248       aB.Add(aComp,aNewShape);
00249       isAddComp = Standard_True;
00250     }
00251     
00252   }
00253   if(isDone) {
00254     //for getting correct solids class ShapeFix_Solid will be used.
00255     if(isAddSol) {
00256       Handle(ShapeFix_Solid) aSfSol = new ShapeFix_Solid(aSol);
00257       aSfSol->FixShellMode()= Standard_False;
00258       aSfSol->Perform();
00259       TopoDS_Shape aresSol = aSfSol->Shape();
00260       if(!isAddComp) 
00261         theNewShape = aresSol;
00262       else 
00263         aB.Add(aComp,aresSol);
00264     }
00265     else if(isAddComp)
00266         theNewShape = aComp;
00267     else
00268       theNewShape.Nullify();
00269   }
00270   else
00271     theNewShape = theShape; 
00272   return isDone;
00273 }
00274 //=======================================================================
00275 //function : IsManifold
00276 //purpose  : function for definition manifold shell
00277 //=======================================================================
00278 Standard_Boolean ShHealOper_RemoveFace::isManifold(const TopoDS_Shell& aShell)
00279 {
00280   Standard_Boolean IsManifold = Standard_True;
00281   TopExp_Explorer aExp(aShell,TopAbs_EDGE);
00282   for( ; aExp.More() && IsManifold; aExp.Next()) {
00283     const TopTools_ListOfShape& als = myMapEdgesFace.FindFromKey(aExp.Current());
00284     IsManifold = (als.Extent() <=2 ); 
00285   }
00286   return IsManifold;
00287 }
00288 
00289 //=======================================================================
00290 //function : getResultShell
00291 //purpose  : function for avoiding empty shall or shell containing one face.
00292 //=======================================================================
00293 static TopoDS_Shape getResultShell(const TopoDS_Shape& theNewShell)
00294 {
00295   TopoDS_Shape rs;
00296   Standard_Integer NbFacesShell =0;
00297   TopoDS_Shape aF;
00298   TopoDS_Iterator aI(theNewShell,Standard_False);
00299   for(; aI.More(); aI.Next(),NbFacesShell++)
00300     aF = aI.Value();
00301   if(NbFacesShell >1)
00302     rs = theNewShell;
00303   else if(!aF.IsNull())
00304     rs = aF;
00305   return rs;
00306 }
00307 
00308 //=======================================================================
00309 //function : removeFaces
00310 //purpose  : function for removing faces from shell
00311 //=======================================================================
00312 
00313 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shell& theShell,
00314                                                     TopoDS_Shape& theNewShape)
00315 {
00316   
00317   Standard_Boolean aIsRemove = Standard_False;
00318   //TopoDS_Shape aShape = myReShape->Apply(theShape);
00319   //removing faces from shell.
00320   TopoDS_Iterator aIterFaces(theShell,Standard_False);
00321   for(; aIterFaces.More() && myMapFaces.Extent(); aIterFaces.Next()) {
00322 
00323     if(!myMapFaces.Contains(aIterFaces.Value()))
00324       continue;
00325     TopoDS_Face aFace = TopoDS::Face( aIterFaces.Value());
00326     removePCurve(aFace);
00327     aIsRemove  = Standard_True;
00328     myContext->Remove(aFace);
00329     myMapFaces.Remove(aFace);
00330   }
00331   if(aIsRemove) {
00332     TopoDS_Shape aNewShape = myContext->Apply(theShell);
00333     //avoiding empty shell and shell containing one face.
00334     TopoDS_Shape aresShape = getResultShell(aNewShape);
00335     if(aresShape.IsNull()) {
00336       myContext->Remove(aNewShape);
00337       theNewShape.Nullify();
00338     }
00339     else if(aresShape.ShapeType() == TopAbs_FACE) {
00340       myContext->Replace(aNewShape,aresShape);
00341       theNewShape = aresShape;
00342     }
00343     else if(aresShape.ShapeType() == TopAbs_SHELL) {
00344       //obtaining correct shell or compound with help class ShapeFix_Shell.
00345       Standard_Boolean isManifShell = isManifold(theShell);
00346       Handle(ShapeFix_Shell) aFixShell = new ShapeFix_Shell;
00347       aFixShell->FixFaceOrientation(TopoDS::Shell(aresShape),Standard_True,!isManifShell);
00348       TopoDS_Shape aFixShape = aFixShell->Shape();
00349       TopoDS_Shape areplShape;
00350       isReplace(aFixShape,areplShape);
00351       myContext->Replace(aNewShape,areplShape);
00352       theNewShape = areplShape;
00353     }
00354   }
00355   else theNewShape = theShell;
00356   return aIsRemove;
00357 }
00358 //=======================================================================
00359 //function : isReplace
00360 //purpose  : method to avoiding empty compounds and shells.
00361 //=======================================================================
00362 
00363 Standard_Boolean ShHealOper_RemoveFace::isReplace(const TopoDS_Shape& theShape, 
00364                                                   TopoDS_Shape& theNewShape)
00365 {
00366   
00367   Standard_Boolean isChange = Standard_False;
00368   TopTools_SequenceOfShape aSeqShapes;
00369   if(theShape.ShapeType() == TopAbs_COMPOUND || theShape.ShapeType() == TopAbs_COMPSOLID ||
00370      theShape.ShapeType() == TopAbs_SOLID) {
00371     TopoDS_Iterator aEs(theShape);
00372     for( ; aEs.More(); aEs.Next()) {
00373       TopoDS_Shape aNewShell = aEs.Value();
00374       if(aNewShell.ShapeType()!= TopAbs_SHELL) {
00375         aSeqShapes.Append(aNewShell);
00376         continue;
00377       }
00378       TopoDS_Shape as = getResultShell(TopoDS::Shell(aNewShell));
00379       isChange = (as.IsNull() || (as.ShapeType() == TopAbs_FACE));
00380       if(!as.IsNull()) {
00381         aSeqShapes.Append(as);
00382       }
00383     }
00384   }
00385   else if(theShape.ShapeType() == TopAbs_SHELL) {
00386     TopoDS_Shape aSh = getResultShell(TopoDS::Shell(theShape));
00387     isChange = (aSh.IsNull() || (aSh.ShapeType() == TopAbs_FACE));
00388     if(!aSh.IsNull())
00389       aSeqShapes.Append(aSh);
00390   }
00391   else aSeqShapes.Append(theShape);
00392 
00393   if(aSeqShapes.IsEmpty())
00394     return Standard_True;
00395 
00396   if(isChange) {
00397     if(aSeqShapes.Length() == 1)
00398       theNewShape = aSeqShapes.Value(1);
00399     else if (aSeqShapes.Length() > 1) {
00400       TopoDS_Compound aComp1;
00401       BRep_Builder aBB;
00402       aBB.MakeCompound(aComp1);
00403       Standard_Integer kk =1;
00404       for( ; kk <=  aSeqShapes.Length(); kk++)
00405         aBB.Add(aComp1,aSeqShapes.Value(kk));
00406       if(aSeqShapes.Length())
00407         theNewShape = aComp1;
00408     }
00409   }
00410   else
00411     theNewShape = theShape;
00412   return isChange;
00413 }
00414 //=======================================================================
00415 //function : removePCurve
00416 //purpose  : 
00417 //=======================================================================
00418 
00419 void ShHealOper_RemoveFace::removePCurve(const TopoDS_Face& theFace)
00420 {
00421   //removing pcurves belonging removed face.
00422   Handle(Geom_Surface) aSurfDel = BRep_Tool::Surface(theFace);
00423   for(TopExp_Explorer aExpEdges(theFace,TopAbs_EDGE);  aExpEdges.More();  aExpEdges.Next()) {
00424     const TopTools_ListOfShape& alFaces = myMapEdgesFace.FindFromKey(aExpEdges.Current());
00425     Standard_Boolean aIsDeleted = Standard_True;
00426     
00427     //pcurve will be removed if containing this edge faces have different surfaces.
00428     TopTools_ListIteratorOfListOfShape aIterOtherFace(alFaces);
00429     for(; aIterOtherFace.More() && aIsDeleted ; aIterOtherFace.Next()) {
00430       if(aIterOtherFace.Value().IsSame(theFace))
00431          continue;
00432          TopoDS_Face aFaceOther = TopoDS::Face(aIterOtherFace.Value());
00433          Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFaceOther);
00434          aIsDeleted = (aSurf != aSurfDel);
00435     }
00436     
00437     TopoDS_Edge aEdge = TopoDS::Edge(myContext->Apply(aExpEdges.Current()));
00438     ShapeBuild_Edge aSbe;
00439     TopoDS_Edge aNewEdge = aSbe.Copy(aEdge,Standard_False);
00440     if(aIsDeleted) {
00441       aSbe.RemovePCurve(aNewEdge,aSurfDel);
00442       myContext->Replace(aEdge,aNewEdge);
00443       
00444     }
00445     
00446   }
00447 }
00448