1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 // File: ShHealOper_RemoveFace.cxx
22 // Created: 16.04.04 12:12:38
23 // Author: Galina KULIKOVA
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>
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>
46 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_ListIteratorOfListOfShape.hxx>
50 //=======================================================================
51 //function : ShHealOper_RemoveFace()
52 //purpose : Constructor
53 //=======================================================================
54 ShHealOper_RemoveFace::ShHealOper_RemoveFace () :
58 //=======================================================================
59 //function : ShHealOper_RemoveFace
61 //=======================================================================
63 ShHealOper_RemoveFace::ShHealOper_RemoveFace ( const TopoDS_Shape& theShape )
64 //ShHealOper_Tool(theShape)
68 //=======================================================================
71 //=======================================================================
73 void ShHealOper_RemoveFace::Init(const TopoDS_Shape& theShape)
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);
82 //=======================================================================
84 //purpose : remove all faces from initial shape
85 //=======================================================================
87 Standard_Boolean ShHealOper_RemoveFace::Perform()
89 myDone = Standard_False;
90 myErrorStatus = ShHealOper_NotError;
91 if(myInitShape.IsNull()) {
92 myErrorStatus = ShHealOper_InvalidParameters;
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;
102 TopoDS_Shape aNewShape = myContext->Apply(myInitShape);
103 isReplace(aNewShape,myResultShape);
104 myContext->Replace(aNewShape,myResultShape);
108 //=======================================================================
110 //purpose : remove faces specified by sequence of faces from initial shape.
111 //=======================================================================
113 Standard_Boolean ShHealOper_RemoveFace::Perform(const TopTools_SequenceOfShape& theRemoveFaces)
115 myDone = Standard_False;
116 myErrorStatus = ShHealOper_NotError;
117 if(myInitShape.IsNull()) {
118 myErrorStatus = ShHealOper_InvalidParameters;
121 if(theRemoveFaces.IsEmpty())
122 return Standard_False;
125 Standard_Integer i=1;
126 for( ; i <= theRemoveFaces.Length(); i++)
127 myMapFaces.Add(theRemoveFaces.Value(i));
129 myDone = removeFaces(myInitShape,myResultShape);
133 //=======================================================================
134 //function : removeFaces
136 //=======================================================================
138 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shape& theShape,
139 TopoDS_Shape& theNewShape)
141 Standard_Boolean isDone = Standard_False;
143 TopAbs_ShapeEnum aType = theShape.ShapeType();
144 theNewShape = theShape;
145 if(!myMapFaces.Extent())
147 if( aType == TopAbs_WIRE || aType == TopAbs_EDGE || aType == TopAbs_VERTEX)
149 if(aType == TopAbs_FACE && myMapFaces.Contains(theShape)) {
150 removePCurve(TopoDS::Face(theShape));
152 myContext->Remove(theShape);
153 myMapFaces.Remove(theShape);
154 //theNewShape = TopoDS_Shape();
155 theNewShape.Nullify();
156 isDone = Standard_True;
158 else if(aType == TopAbs_SHELL) {
159 isDone = removeFaces(TopoDS::Shell(theShape),theNewShape);
162 else if(aType == TopAbs_SOLID) {
163 isDone = removeFaces(TopoDS::Solid(theShape),theNewShape);
164 myContext->Replace(theShape,theNewShape);
166 else if(aType == TopAbs_COMPSOLID) {
168 //in the case of compsolid method for removing faces for solid
171 TopExp_Explorer aExpShell(theShape,TopAbs_SHELL);
175 for( ; aExpShell.More(); aExpShell.Next()) {
176 aB.Add(aSol,aExpShell.Current());
178 TopoDS_Shape aNewShape;
179 isDone = removeFaces(aSol,aNewShape);
181 myContext->Replace(theShape,theNewShape);
184 else if(aType == TopAbs_COMPOUND) {
185 //in the case of compounf faces will be removed from each part of compound separately
187 TopoDS_Compound aComp;
188 TopoDS_Iterator aItShape(theShape,Standard_False);
190 aB.MakeCompound(aComp);
191 Standard_Integer nbs =0;
192 for( ; aItShape.More() ; aItShape.Next()) {
194 TopoDS_Shape aNShape;
195 if( removeFaces(aItShape.Value(),aNShape)) {
196 isDone = Standard_True;
197 myContext->Replace(aItShape.Value(),aNShape);
199 if(!aNShape.IsNull()) {
200 aB.Add(aComp,aNShape);
208 theNewShape =TopoDS_Shape();
209 myContext->Replace(theShape,theNewShape);
215 //=======================================================================
216 //function : removeFaces
217 //purpose : function for removing faces from solid
218 //=======================================================================
220 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Solid& theShape,
221 TopoDS_Shape& theNewShape)
223 Standard_Boolean isDone = Standard_False;
227 TopoDS_Compound aComp;
228 aB.MakeCompound(aComp);
229 Standard_Boolean isAddSol = Standard_False, isAddComp = Standard_False;
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;
239 if(aNewShape.IsNull())
241 else if(aNewShape.ShapeType() == TopAbs_SHELL ) {
242 aB.Add(aSol,aNewShape);
243 isAddSol = Standard_True;
246 aB.Add(aComp,aNewShape);
247 isAddComp = Standard_True;
252 //for getting correct solids class ShapeFix_Solid will be used.
254 Handle(ShapeFix_Solid) aSfSol = new ShapeFix_Solid(aSol);
255 aSfSol->FixShellMode()= Standard_False;
257 TopoDS_Shape aresSol = aSfSol->Shape();
259 theNewShape = aresSol;
261 aB.Add(aComp,aresSol);
266 theNewShape.Nullify();
269 theNewShape = theShape;
272 //=======================================================================
273 //function : IsManifold
274 //purpose : function for definition manifold shell
275 //=======================================================================
276 Standard_Boolean ShHealOper_RemoveFace::isManifold(const TopoDS_Shell& aShell)
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 );
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)
294 Standard_Integer NbFacesShell =0;
296 TopoDS_Iterator aI(theNewShell,Standard_False);
297 for(; aI.More(); aI.Next(),NbFacesShell++)
301 else if(!aF.IsNull())
306 //=======================================================================
307 //function : removeFaces
308 //purpose : function for removing faces from shell
309 //=======================================================================
311 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shell& theShell,
312 TopoDS_Shape& theNewShape)
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()) {
321 if(!myMapFaces.Contains(aIterFaces.Value()))
323 TopoDS_Face aFace = TopoDS::Face( aIterFaces.Value());
325 aIsRemove = Standard_True;
326 myContext->Remove(aFace);
327 myMapFaces.Remove(aFace);
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();
337 else if(aresShape.ShapeType() == TopAbs_FACE) {
338 myContext->Replace(aNewShape,aresShape);
339 theNewShape = aresShape;
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;
353 else theNewShape = theShell;
356 //=======================================================================
357 //function : isReplace
358 //purpose : method to avoiding empty compounds and shells.
359 //=======================================================================
361 Standard_Boolean ShHealOper_RemoveFace::isReplace(const TopoDS_Shape& theShape,
362 TopoDS_Shape& theNewShape)
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);
376 TopoDS_Shape as = getResultShell(TopoDS::Shell(aNewShell));
377 isChange = (as.IsNull() || (as.ShapeType() == TopAbs_FACE));
379 aSeqShapes.Append(as);
383 else if(theShape.ShapeType() == TopAbs_SHELL) {
384 TopoDS_Shape aSh = getResultShell(TopoDS::Shell(theShape));
385 isChange = (aSh.IsNull() || (aSh.ShapeType() == TopAbs_FACE));
387 aSeqShapes.Append(aSh);
389 else aSeqShapes.Append(theShape);
391 if(aSeqShapes.IsEmpty())
392 return Standard_True;
395 if(aSeqShapes.Length() == 1)
396 theNewShape = aSeqShapes.Value(1);
397 else if (aSeqShapes.Length() > 1) {
398 TopoDS_Compound aComp1;
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;
409 theNewShape = theShape;
412 //=======================================================================
413 //function : removePCurve
415 //=======================================================================
417 void ShHealOper_RemoveFace::removePCurve(const TopoDS_Face& theFace)
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;
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))
430 TopoDS_Face aFaceOther = TopoDS::Face(aIterOtherFace.Value());
431 Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFaceOther);
432 aIsDeleted = (aSurf != aSurfDel);
435 TopoDS_Edge aEdge = TopoDS::Edge(myContext->Apply(aExpEdges.Current()));
436 ShapeBuild_Edge aSbe;
437 TopoDS_Edge aNewEdge = aSbe.Copy(aEdge,Standard_False);
439 aSbe.RemovePCurve(aNewEdge,aSurfDel);
440 myContext->Replace(aEdge,aNewEdge);