1 // File: ShHealOper_RemoveFace.cxx
2 // Created: 16.04.04 12:12:38
3 // Author: Galina KULIKOVA
4 // < MODULE = KERNEL> <PACKAGE = ShHealOper> : <Shape Healing Operations>
5 // Copyright (C) 2003 CEA
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <ShHealOper_RemoveFace.hxx>
24 #include <BRepTools_ReShape.hxx>
25 #include <TopoDS_Shape.hxx>
26 #include <TopAbs_ShapeEnum.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS_Compound.hxx>
29 #include <TopoDS_Solid.hxx>
30 #include <TopoDS_Shell.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <BRep_Builder.hxx>
33 #include <TopoDS_Iterator.hxx>
35 #include <TopTools_ListOfShape.hxx>
36 #include <BRep_Tool.hxx>
37 #include <Geom_Surface.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <ShapeBuild_Edge.hxx>
40 #include <ShapeFix_Shell.hxx>
41 #include <ShapeFix_Solid.hxx>
42 #include <TopTools_SequenceOfShape.hxx>
44 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
48 //=======================================================================
49 //function : ShHealOper_RemoveFace()
50 //purpose : Constructor
51 //=======================================================================
52 ShHealOper_RemoveFace::ShHealOper_RemoveFace () :
56 //=======================================================================
57 //function : ShHealOper_RemoveFace
59 //=======================================================================
61 ShHealOper_RemoveFace::ShHealOper_RemoveFace ( const TopoDS_Shape& theShape )
62 //ShHealOper_Tool(theShape)
66 //=======================================================================
69 //=======================================================================
71 void ShHealOper_RemoveFace::Init(const TopoDS_Shape& theShape)
73 //myDone = Standard_False;
74 //myInitShape = theShape;
75 //myContext->Apply(myInitShape);
76 ShHealOper_Tool::Init(theShape);
77 myMapEdgesFace.Clear();
78 TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,myMapEdgesFace);
80 //=======================================================================
82 //purpose : remove all faces from initial shape
83 //=======================================================================
85 Standard_Boolean ShHealOper_RemoveFace::Perform()
87 myDone = Standard_False;
88 myErrorStatus = ShHealOper_NotError;
89 if(myInitShape.IsNull()) {
90 myErrorStatus = ShHealOper_InvalidParameters;
93 TopExp_Explorer aExp(myInitShape,TopAbs_FACE);
94 for( ; aExp.More(); aExp.Next()) {
95 removePCurve(TopoDS::Face(aExp.Current()));
96 myContext->Remove(aExp.Current());
97 myDone = Standard_True;
100 TopoDS_Shape aNewShape = myContext->Apply(myInitShape);
101 isReplace(aNewShape,myResultShape);
102 myContext->Replace(aNewShape,myResultShape);
106 //=======================================================================
108 //purpose : remove faces specified by sequence of faces from initial shape.
109 //=======================================================================
111 Standard_Boolean ShHealOper_RemoveFace::Perform(const TopTools_SequenceOfShape& theRemoveFaces)
113 myDone = Standard_False;
114 myErrorStatus = ShHealOper_NotError;
115 if(myInitShape.IsNull()) {
116 myErrorStatus = ShHealOper_InvalidParameters;
119 if(theRemoveFaces.IsEmpty())
120 return Standard_False;
123 Standard_Integer i=1;
124 for( ; i <= theRemoveFaces.Length(); i++)
125 myMapFaces.Add(theRemoveFaces.Value(i));
127 myDone = removeFaces(myInitShape,myResultShape);
131 //=======================================================================
132 //function : removeFaces
134 //=======================================================================
136 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shape& theShape,
137 TopoDS_Shape& theNewShape)
139 Standard_Boolean isDone = Standard_False;
141 TopAbs_ShapeEnum aType = theShape.ShapeType();
142 theNewShape = theShape;
143 if(!myMapFaces.Extent())
145 if( aType == TopAbs_WIRE || aType == TopAbs_EDGE || aType == TopAbs_VERTEX)
147 if(aType == TopAbs_FACE && myMapFaces.Contains(theShape)) {
148 removePCurve(TopoDS::Face(theShape));
150 myContext->Remove(theShape);
151 myMapFaces.Remove(theShape);
152 //theNewShape = TopoDS_Shape();
153 theNewShape.Nullify();
154 isDone = Standard_True;
156 else if(aType == TopAbs_SHELL) {
157 isDone = removeFaces(TopoDS::Shell(theShape),theNewShape);
160 else if(aType == TopAbs_SOLID) {
161 isDone = removeFaces(TopoDS::Solid(theShape),theNewShape);
162 myContext->Replace(theShape,theNewShape);
164 else if(aType == TopAbs_COMPSOLID) {
166 //in the case of compsolid method for removing faces for solid
169 TopExp_Explorer aExpShell(theShape,TopAbs_SHELL);
173 for( ; aExpShell.More(); aExpShell.Next()) {
174 aB.Add(aSol,aExpShell.Current());
176 TopoDS_Shape aNewShape;
177 isDone = removeFaces(aSol,aNewShape);
179 myContext->Replace(theShape,theNewShape);
182 else if(aType == TopAbs_COMPOUND) {
183 //in the case of compounf faces will be removed from each part of compound separately
185 TopoDS_Compound aComp;
186 TopoDS_Iterator aItShape(theShape,Standard_False);
188 aB.MakeCompound(aComp);
189 Standard_Integer nbs =0;
190 for( ; aItShape.More() ; aItShape.Next()) {
192 TopoDS_Shape aNShape;
193 if( removeFaces(aItShape.Value(),aNShape)) {
194 isDone = Standard_True;
195 myContext->Replace(aItShape.Value(),aNShape);
197 if(!aNShape.IsNull()) {
198 aB.Add(aComp,aNShape);
206 theNewShape =TopoDS_Shape();
207 myContext->Replace(theShape,theNewShape);
213 //=======================================================================
214 //function : removeFaces
215 //purpose : function for removing faces from solid
216 //=======================================================================
218 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Solid& theShape,
219 TopoDS_Shape& theNewShape)
221 Standard_Boolean isDone = Standard_False;
225 TopoDS_Compound aComp;
226 aB.MakeCompound(aComp);
227 Standard_Boolean isAddSol = Standard_False, isAddComp = Standard_False;
229 //firslty faces will be deleted from each shell.
230 TopoDS_Iterator aItSol(theShape,Standard_False);
231 for( ; aItSol.More(); aItSol.Next()) {
232 TopoDS_Shape aSh = aItSol.Value();
233 TopoDS_Shape aNewShape;
234 if(removeFaces(aSh,aNewShape))
235 isDone = Standard_True;
237 if(aNewShape.IsNull())
239 else if(aNewShape.ShapeType() == TopAbs_SHELL ) {
240 aB.Add(aSol,aNewShape);
241 isAddSol = Standard_True;
244 aB.Add(aComp,aNewShape);
245 isAddComp = Standard_True;
250 //for getting correct solids class ShapeFix_Solid will be used.
252 Handle(ShapeFix_Solid) aSfSol = new ShapeFix_Solid(aSol);
253 aSfSol->FixShellMode()= Standard_False;
255 TopoDS_Shape aresSol = aSfSol->Shape();
257 theNewShape = aresSol;
259 aB.Add(aComp,aresSol);
264 theNewShape.Nullify();
267 theNewShape = theShape;
270 //=======================================================================
271 //function : IsManifold
272 //purpose : function for definition manifold shell
273 //=======================================================================
274 Standard_Boolean ShHealOper_RemoveFace::isManifold(const TopoDS_Shell& aShell)
276 Standard_Boolean IsManifold = Standard_True;
277 TopExp_Explorer aExp(aShell,TopAbs_EDGE);
278 for( ; aExp.More() && IsManifold; aExp.Next()) {
279 const TopTools_ListOfShape& als = myMapEdgesFace.FindFromKey(aExp.Current());
280 IsManifold = (als.Extent() <=2 );
285 //=======================================================================
286 //function : getResultShell
287 //purpose : function for avoiding empty shall or shell containing one face.
288 //=======================================================================
289 static TopoDS_Shape getResultShell(const TopoDS_Shape& theNewShell)
292 Standard_Integer NbFacesShell =0;
294 TopoDS_Iterator aI(theNewShell,Standard_False);
295 for(; aI.More(); aI.Next(),NbFacesShell++)
299 else if(!aF.IsNull())
304 //=======================================================================
305 //function : removeFaces
306 //purpose : function for removing faces from shell
307 //=======================================================================
309 Standard_Boolean ShHealOper_RemoveFace::removeFaces(const TopoDS_Shell& theShell,
310 TopoDS_Shape& theNewShape)
313 Standard_Boolean aIsRemove = Standard_False;
314 //TopoDS_Shape aShape = myReShape->Apply(theShape);
315 //removing faces from shell.
316 TopoDS_Iterator aIterFaces(theShell,Standard_False);
317 for(; aIterFaces.More() && myMapFaces.Extent(); aIterFaces.Next()) {
319 if(!myMapFaces.Contains(aIterFaces.Value()))
321 TopoDS_Face aFace = TopoDS::Face( aIterFaces.Value());
323 aIsRemove = Standard_True;
324 myContext->Remove(aFace);
325 myMapFaces.Remove(aFace);
328 TopoDS_Shape aNewShape = myContext->Apply(theShell);
329 //avoiding empty shell and shell containing one face.
330 TopoDS_Shape aresShape = getResultShell(aNewShape);
331 if(aresShape.IsNull()) {
332 myContext->Remove(aNewShape);
333 theNewShape.Nullify();
335 else if(aresShape.ShapeType() == TopAbs_FACE) {
336 myContext->Replace(aNewShape,aresShape);
337 theNewShape = aresShape;
339 else if(aresShape.ShapeType() == TopAbs_SHELL) {
340 //obtaining correct shell or compound with help class ShapeFix_Shell.
341 Standard_Boolean isManifShell = isManifold(theShell);
342 Handle(ShapeFix_Shell) aFixShell = new ShapeFix_Shell;
343 aFixShell->FixFaceOrientation(TopoDS::Shell(aresShape),Standard_True,!isManifShell);
344 TopoDS_Shape aFixShape = aFixShell->Shape();
345 TopoDS_Shape areplShape;
346 isReplace(aFixShape,areplShape);
347 myContext->Replace(aNewShape,areplShape);
348 theNewShape = areplShape;
351 else theNewShape = theShell;
354 //=======================================================================
355 //function : isReplace
356 //purpose : method to avoiding empty compounds and shells.
357 //=======================================================================
359 Standard_Boolean ShHealOper_RemoveFace::isReplace(const TopoDS_Shape& theShape,
360 TopoDS_Shape& theNewShape)
363 Standard_Boolean isChange = Standard_False;
364 TopTools_SequenceOfShape aSeqShapes;
365 if(theShape.ShapeType() == TopAbs_COMPOUND || theShape.ShapeType() == TopAbs_COMPSOLID ||
366 theShape.ShapeType() == TopAbs_SOLID) {
367 TopoDS_Iterator aEs(theShape);
368 for( ; aEs.More(); aEs.Next()) {
369 TopoDS_Shape aNewShell = aEs.Value();
370 if(aNewShell.ShapeType()!= TopAbs_SHELL) {
371 aSeqShapes.Append(aNewShell);
374 TopoDS_Shape as = getResultShell(TopoDS::Shell(aNewShell));
375 isChange = (as.IsNull() || (as.ShapeType() == TopAbs_FACE));
377 aSeqShapes.Append(as);
381 else if(theShape.ShapeType() == TopAbs_SHELL) {
382 TopoDS_Shape aSh = getResultShell(TopoDS::Shell(theShape));
383 isChange = (aSh.IsNull() || (aSh.ShapeType() == TopAbs_FACE));
385 aSeqShapes.Append(aSh);
387 else aSeqShapes.Append(theShape);
389 if(aSeqShapes.IsEmpty())
390 return Standard_True;
393 if(aSeqShapes.Length() == 1)
394 theNewShape = aSeqShapes.Value(1);
395 else if (aSeqShapes.Length() > 1) {
396 TopoDS_Compound aComp1;
398 aBB.MakeCompound(aComp1);
399 Standard_Integer kk =1;
400 for( ; kk <= aSeqShapes.Length(); kk++)
401 aBB.Add(aComp1,aSeqShapes.Value(kk));
402 if(aSeqShapes.Length())
403 theNewShape = aComp1;
407 theNewShape = theShape;
410 //=======================================================================
411 //function : removePCurve
413 //=======================================================================
415 void ShHealOper_RemoveFace::removePCurve(const TopoDS_Face& theFace)
417 //removing pcurves belonging removed face.
418 Handle(Geom_Surface) aSurfDel = BRep_Tool::Surface(theFace);
419 for(TopExp_Explorer aExpEdges(theFace,TopAbs_EDGE); aExpEdges.More(); aExpEdges.Next()) {
420 const TopTools_ListOfShape& alFaces = myMapEdgesFace.FindFromKey(aExpEdges.Current());
421 Standard_Boolean aIsDeleted = Standard_True;
423 //pcurve will be removed if containing this edge faces have different surfaces.
424 TopTools_ListIteratorOfListOfShape aIterOtherFace(alFaces);
425 for(; aIterOtherFace.More() && aIsDeleted ; aIterOtherFace.Next()) {
426 if(aIterOtherFace.Value().IsSame(theFace))
428 TopoDS_Face aFaceOther = TopoDS::Face(aIterOtherFace.Value());
429 Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFaceOther);
430 aIsDeleted = (aSurf != aSurfDel);
433 TopoDS_Edge aEdge = TopoDS::Edge(myContext->Apply(aExpEdges.Current()));
434 ShapeBuild_Edge aSbe;
435 TopoDS_Edge aNewEdge = aSbe.Copy(aEdge,Standard_False);
437 aSbe.RemovePCurve(aNewEdge,aSurfDel);
438 myContext->Replace(aEdge,aNewEdge);