1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: ShHealOper_RemoveFace.cxx
24 // Created: 16.04.04 12:12:38
25 // Author: Galina KULIKOVA
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>
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>
48 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
49 #include <TopTools_ListIteratorOfListOfShape.hxx>
52 //=======================================================================
53 //function : ShHealOper_RemoveFace()
54 //purpose : Constructor
55 //=======================================================================
56 ShHealOper_RemoveFace::ShHealOper_RemoveFace () :
60 //=======================================================================
61 //function : ShHealOper_RemoveFace
63 //=======================================================================
65 ShHealOper_RemoveFace::ShHealOper_RemoveFace ( const TopoDS_Shape& theShape )
66 //ShHealOper_Tool(theShape)
70 //=======================================================================
73 //=======================================================================
75 void ShHealOper_RemoveFace::Init(const TopoDS_Shape& theShape)
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);
84 //=======================================================================
86 //purpose : remove all faces from initial shape
87 //=======================================================================
89 Standard_Boolean ShHealOper_RemoveFace::Perform()
91 myDone = Standard_False;
92 myErrorStatus = ShHealOper_NotError;
93 if(myInitShape.IsNull()) {
94 myErrorStatus = ShHealOper_InvalidParameters;
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;
104 TopoDS_Shape aNewShape = myContext->Apply(myInitShape);
105 isReplace(aNewShape,myResultShape);
106 myContext->Replace(aNewShape,myResultShape);
110 //=======================================================================
112 //purpose : remove faces specified by sequence of faces from initial shape.
113 //=======================================================================
115 Standard_Boolean ShHealOper_RemoveFace::Perform(const TopTools_SequenceOfShape& theRemoveFaces)
117 myDone = Standard_False;
118 myErrorStatus = ShHealOper_NotError;
119 if(myInitShape.IsNull()) {
120 myErrorStatus = ShHealOper_InvalidParameters;
123 if(theRemoveFaces.IsEmpty())
124 return Standard_False;
127 Standard_Integer i=1;
128 for( ; i <= theRemoveFaces.Length(); i++)
129 myMapFaces.Add(theRemoveFaces.Value(i));
131 myDone = removeFaces(myInitShape,myResultShape);
135 //=======================================================================
136 //function : removeFaces
138 //=======================================================================
140 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shape& theShape,
141 TopoDS_Shape& theNewShape)
143 Standard_Boolean isDone = Standard_False;
145 TopAbs_ShapeEnum aType = theShape.ShapeType();
146 theNewShape = theShape;
147 if(!myMapFaces.Extent())
149 if( aType == TopAbs_WIRE || aType == TopAbs_EDGE || aType == TopAbs_VERTEX)
151 if(aType == TopAbs_FACE && myMapFaces.Contains(theShape)) {
152 removePCurve(TopoDS::Face(theShape));
154 myContext->Remove(theShape);
155 myMapFaces.Remove(theShape);
156 //theNewShape = TopoDS_Shape();
157 theNewShape.Nullify();
158 isDone = Standard_True;
160 else if(aType == TopAbs_SHELL) {
161 isDone = removeFaces(TopoDS::Shell(theShape),theNewShape);
164 else if(aType == TopAbs_SOLID) {
165 isDone = removeFaces(TopoDS::Solid(theShape),theNewShape);
166 myContext->Replace(theShape,theNewShape);
168 else if(aType == TopAbs_COMPSOLID) {
170 //in the case of compsolid method for removing faces for solid
173 TopExp_Explorer aExpShell(theShape,TopAbs_SHELL);
177 for( ; aExpShell.More(); aExpShell.Next()) {
178 aB.Add(aSol,aExpShell.Current());
180 TopoDS_Shape aNewShape;
181 isDone = removeFaces(aSol,aNewShape);
183 myContext->Replace(theShape,theNewShape);
186 else if(aType == TopAbs_COMPOUND) {
187 //in the case of compounf faces will be removed from each part of compound separately
189 TopoDS_Compound aComp;
190 TopoDS_Iterator aItShape(theShape,Standard_False);
192 aB.MakeCompound(aComp);
193 Standard_Integer nbs =0;
194 for( ; aItShape.More() ; aItShape.Next()) {
196 TopoDS_Shape aNShape;
197 if( removeFaces(aItShape.Value(),aNShape)) {
198 isDone = Standard_True;
199 myContext->Replace(aItShape.Value(),aNShape);
201 if(!aNShape.IsNull()) {
202 aB.Add(aComp,aNShape);
210 theNewShape =TopoDS_Shape();
211 myContext->Replace(theShape,theNewShape);
217 //=======================================================================
218 //function : removeFaces
219 //purpose : function for removing faces from solid
220 //=======================================================================
222 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Solid& theShape,
223 TopoDS_Shape& theNewShape)
225 Standard_Boolean isDone = Standard_False;
229 TopoDS_Compound aComp;
230 aB.MakeCompound(aComp);
231 Standard_Boolean isAddSol = Standard_False, isAddComp = Standard_False;
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;
241 if(aNewShape.IsNull())
243 else if(aNewShape.ShapeType() == TopAbs_SHELL ) {
244 aB.Add(aSol,aNewShape);
245 isAddSol = Standard_True;
248 aB.Add(aComp,aNewShape);
249 isAddComp = Standard_True;
254 //for getting correct solids class ShapeFix_Solid will be used.
256 Handle(ShapeFix_Solid) aSfSol = new ShapeFix_Solid(aSol);
257 aSfSol->FixShellMode()= Standard_False;
259 TopoDS_Shape aresSol = aSfSol->Shape();
261 theNewShape = aresSol;
263 aB.Add(aComp,aresSol);
268 theNewShape.Nullify();
271 theNewShape = theShape;
274 //=======================================================================
275 //function : IsManifold
276 //purpose : function for definition manifold shell
277 //=======================================================================
278 Standard_Boolean ShHealOper_RemoveFace::isManifold(const TopoDS_Shell& aShell)
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 );
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)
296 Standard_Integer NbFacesShell =0;
298 TopoDS_Iterator aI(theNewShell,Standard_False);
299 for(; aI.More(); aI.Next(),NbFacesShell++)
303 else if(!aF.IsNull())
308 //=======================================================================
309 //function : removeFaces
310 //purpose : function for removing faces from shell
311 //=======================================================================
313 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shell& theShell,
314 TopoDS_Shape& theNewShape)
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()) {
323 if(!myMapFaces.Contains(aIterFaces.Value()))
325 TopoDS_Face aFace = TopoDS::Face( aIterFaces.Value());
327 aIsRemove = Standard_True;
328 myContext->Remove(aFace);
329 myMapFaces.Remove(aFace);
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();
339 else if(aresShape.ShapeType() == TopAbs_FACE) {
340 myContext->Replace(aNewShape,aresShape);
341 theNewShape = aresShape;
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;
355 else theNewShape = theShell;
358 //=======================================================================
359 //function : isReplace
360 //purpose : method to avoiding empty compounds and shells.
361 //=======================================================================
363 Standard_Boolean ShHealOper_RemoveFace::isReplace(const TopoDS_Shape& theShape,
364 TopoDS_Shape& theNewShape)
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);
378 TopoDS_Shape as = getResultShell(TopoDS::Shell(aNewShell));
379 isChange = (as.IsNull() || (as.ShapeType() == TopAbs_FACE));
381 aSeqShapes.Append(as);
385 else if(theShape.ShapeType() == TopAbs_SHELL) {
386 TopoDS_Shape aSh = getResultShell(TopoDS::Shell(theShape));
387 isChange = (aSh.IsNull() || (aSh.ShapeType() == TopAbs_FACE));
389 aSeqShapes.Append(aSh);
391 else aSeqShapes.Append(theShape);
393 if(aSeqShapes.IsEmpty())
394 return Standard_True;
397 if(aSeqShapes.Length() == 1)
398 theNewShape = aSeqShapes.Value(1);
399 else if (aSeqShapes.Length() > 1) {
400 TopoDS_Compound aComp1;
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;
411 theNewShape = theShape;
414 //=======================================================================
415 //function : removePCurve
417 //=======================================================================
419 void ShHealOper_RemoveFace::removePCurve(const TopoDS_Face& theFace)
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;
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))
432 TopoDS_Face aFaceOther = TopoDS::Face(aIterOtherFace.Value());
433 Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFaceOther);
434 aIsDeleted = (aSurf != aSurfDel);
437 TopoDS_Edge aEdge = TopoDS::Edge(myContext->Apply(aExpEdges.Current()));
438 ShapeBuild_Edge aSbe;
439 TopoDS_Edge aNewEdge = aSbe.Copy(aEdge,Standard_False);
441 aSbe.RemovePCurve(aNewEdge,aSurfDel);
442 myContext->Replace(aEdge,aNewEdge);