Salome HOME
b0f8e4206a43a007eca91c3fdc28a1af03341fcb
[modules/geom.git] / src / ShHealOper / ShHealOper_Sewing.cxx
1 // File:      ShHealOper_Sewing.cxx
2 // Created:   29.04.04 15:07:10
3 // Author:    Galina KULIKOVA
4 //  < MODULE = KERNEL> <PACKAGE = ShHealOper> : <Shape Healing Operations>
5 //  Copyright (C) 2003  CEA
6 //
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.
11 //
12
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.
17 //
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
21 //
22
23
24 #include <ShHealOper_Sewing.hxx>
25 #include <TopExp_Explorer.hxx>
26 #include <TopoDS_Shell.hxx>
27 #include <BRep_Builder.hxx>
28 #include <ShapeFix_Shell.hxx>
29 #include <TopTools_HSequenceOfShape.hxx>
30 #include <TopoDS_Shell.hxx>
31 #include <BRep_Builder.hxx>
32 #include <ShapeAnalysis_FreeBounds.hxx>
33 #include <TopoDS_Compound.hxx>
34 #include <TopoDS.hxx>
35 #include <TopoDS_Iterator.hxx>
36 #include <TopTools_MapOfShape.hxx>
37 //=======================================================================
38 //function : ShHealOper_Sewing()
39 //purpose  : Constructor
40 //=======================================================================
41
42
43 ShHealOper_Sewing::ShHealOper_Sewing (const TopoDS_Shape& theShape,
44                                      const Standard_Real theTolerance)
45 {
46   Init(theShape);
47   myTolerance = theTolerance;
48 }
49 //=======================================================================
50 //function : Init
51 //purpose  : 
52 //=======================================================================
53
54 void ShHealOper_Sewing::Init(const TopoDS_Shape& theShape)
55 {
56   ShHealOper_Tool::Init(theShape);
57   myTolerance = Precision::Confusion();
58   myEdgesMode = Standard_False;
59   myFacesMode = Standard_True;
60   myNonManifoldMode = Standard_False;
61   myHistoryLevel = TopAbs_FACE;
62 }
63 //=======================================================================
64 //function : Perform
65 //purpose  : 
66 //=======================================================================
67
68 Standard_Boolean ShHealOper_Sewing::Perform()
69 {
70   TopTools_SequenceOfShape theSeqShapes;
71   return sewing(theSeqShapes);
72 }
73 //=======================================================================
74 //function : Perform
75 //purpose  : 
76 //=======================================================================
77
78 Standard_Boolean ShHealOper_Sewing::Perform(const TopTools_SequenceOfShape& theSeqShapes)
79 {
80   return sewing(theSeqShapes);
81 }
82
83 //=======================================================================
84 //function : sewing
85 //purpose  : 
86 //=======================================================================
87
88 Standard_Boolean ShHealOper_Sewing::sewing(const TopTools_SequenceOfShape& theSeqShapes)
89 {
90   myDone = Standard_False;
91   myErrorStatus = ShHealOper_NotError;
92   if(myInitShape.IsNull()) {
93     myErrorStatus = ShHealOper_InvalidParameters;
94     return myDone;
95   }
96   //sewing shape
97   Handle(BRepAlgo_Sewing) aSewing = new BRepAlgo_Sewing;
98   aSewing->Load(myInitShape);
99   aSewing->SetTolerance(myTolerance);
100   aSewing->SetFaceMode(myFacesMode);
101   aSewing->SetFloatingEdgesMode(myEdgesMode);
102   aSewing->SetNonManifoldMode(myNonManifoldMode);
103   Standard_Integer j =1;
104   for( ; j <= theSeqShapes.Length();j++)
105     aSewing->Add(theSeqShapes.Value(j));
106
107   aSewing->Perform();
108   const TopoDS_Shape aSewShape = aSewing->SewedShape();
109   if(aSewShape.IsNull()) {
110     myErrorStatus = ShHealOper_ErrorExecution;
111     return myDone;
112   }
113   if(aSewShape.IsSame(myInitShape))
114     return myDone;
115
116   //analysis either sewing was made by changing number of shells
117   myDone = isSewed(aSewShape);
118
119   //keep modification of the subshapes in the Context.
120   TopExp_Explorer aExp(myInitShape,TopAbs_FACE);
121   for( ; aExp.More(); aExp.Next())
122     myDone = (getModifications( aExp.Current(),aSewing) || myDone);
123
124   TopoDS_Shape aTempShape = myContext->Apply(aSewShape);
125   //obtained shells with fixed orientation for manifold and nonmanifold shells
126   if(myFacesMode) 
127     myDone = getShells(aTempShape) || myDone;
128
129   //obtained manifold wires if sewing edges was performed.
130   if(myEdgesMode) 
131     myDone = getWires(aTempShape) || myDone;
132   
133   if(myDone)
134     myResultShape = myContext->Apply(aTempShape);
135     
136   return myDone;
137 }
138 //=======================================================================
139 //function : getShells
140 //purpose  : 
141 //=======================================================================
142
143 Standard_Boolean ShHealOper_Sewing::getShells(const TopoDS_Shape& theSewShape) const
144 {
145   Standard_Boolean isDone = Standard_False;
146   TopoDS_Shape aTmpShape = theSewShape;
147   if(myNonManifoldMode) {
148     TopoDS_Shell tempShell;
149     BRep_Builder aB;
150     aB.MakeShell(tempShell);
151     
152     for(TopExp_Explorer aExpf(theSewShape,TopAbs_FACE);aExpf.More(); aExpf.Next()) 
153       aB.Add(tempShell,aExpf.Current());
154     aTmpShape = tempShell;
155     myContext->Replace(theSewShape,aTmpShape);
156   }
157   
158   Handle(ShapeFix_Shell) asfs = new ShapeFix_Shell;
159   asfs->SetContext(myContext);
160   TopExp_Explorer aexpShell(aTmpShape,TopAbs_SHELL);
161   for ( ; aexpShell.More(); aexpShell.Next()) 
162     isDone = (asfs->FixFaceOrientation(TopoDS::Shell(aexpShell.Current()),
163                                        Standard_True,myNonManifoldMode) || isDone);
164   
165   return isDone;
166 }
167 //=======================================================================
168 //function : getWires
169 //purpose  : 
170 //=======================================================================
171
172 Standard_Boolean ShHealOper_Sewing::getWires(const TopoDS_Shape& theSewShape) const
173 {
174   if(theSewShape.ShapeType() != TopAbs_COMPOUND)
175     return Standard_False;
176   
177   Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
178   TopExp_Explorer aexpEdges(theSewShape,TopAbs_EDGE,TopAbs_WIRE);
179   for ( ; aexpEdges.More(); aexpEdges.Next()) {
180     aSeqEdges->Append(aexpEdges.Current());
181   }
182   if(aSeqEdges->Length() <2)
183     return Standard_False;
184   //get manifold wires from sewed edges.
185   Standard_Real aTol = 0.;
186   Standard_Boolean aShared = Standard_True;
187   Handle(TopTools_HSequenceOfShape) aTmpWires = new TopTools_HSequenceOfShape;
188   ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdges, aTol, aShared, aTmpWires);
189
190   TopTools_MapOfShape aMapEdges;
191   Standard_Integer i =1;
192   for( ; i <= aSeqEdges->Length(); i++)
193     aMapEdges.Add(aSeqEdges->Value(i));
194   
195   //remove free edges from result shape.
196   TopoDS_Compound aNewComp;
197   deleteFreeEdges(theSewShape,aMapEdges,aNewComp);
198   
199   //add new wires in the result shape.
200   BRep_Builder aB;
201   for( i =1; i <= aTmpWires->Length(); i++) {
202     TopoDS_Iterator aite(aTmpWires->Value(i));
203     Standard_Integer nbe =0;
204     TopoDS_Shape aE;
205     for( ; aite.More() && nbe < 3; aite.Next(),nbe++)
206       aE = aite.Value();
207     if(!nbe)
208       continue;
209     else if(nbe ==1)
210       aB.Add(aNewComp,aE);
211     else
212       aB.Add(aNewComp,aTmpWires->Value(i));
213   }
214   
215   myContext->Replace(theSewShape,aNewComp);
216   return Standard_True;
217 }
218 //=======================================================================
219 //function : getHistory
220 //purpose  : 
221 //=======================================================================
222
223 Standard_Boolean ShHealOper_Sewing::getModifications(const TopoDS_Shape& theShape,
224                                                      const Handle(BRepAlgo_Sewing)& theSewing) const
225 {
226   if((Standard_Integer)theShape.ShapeType() > (Standard_Integer)myHistoryLevel)
227     return Standard_False;
228   
229   Standard_Boolean isDone = theSewing->IsModifiedSubShape(theShape);
230   if(isDone) {
231     TopoDS_Shape aNewShape = theSewing->ModifiedSubShape(theShape);
232     myContext->Replace(theShape,aNewShape);
233   }
234   TopoDS_Iterator aIt(theShape);
235   for( ; aIt.More(); aIt.Next()) {
236     isDone = (getModifications( aIt.Value(),theSewing) || isDone);
237   }
238   return isDone;
239     
240 }
241 //=======================================================================
242 //function : isSewed
243 //purpose  : 
244 //=======================================================================
245
246 Standard_Boolean ShHealOper_Sewing::isSewed(const TopoDS_Shape& theShape) const
247 {
248   Standard_Integer nbNewShells =0;
249   Standard_Integer nbOldShells =0;
250   TopExp_Explorer aExpShells(theShape,TopAbs_SHELL);
251   for( ; aExpShells.More(); aExpShells.Next())
252     nbNewShells++;
253   for( aExpShells.Init(myInitShape,TopAbs_SHELL); aExpShells.More(); aExpShells.Next())
254     nbOldShells++;
255   return (nbNewShells != nbOldShells);
256 }
257 //=======================================================================
258 //function : deleteFreeEdges
259 //purpose  : 
260 //=======================================================================
261
262 void ShHealOper_Sewing::deleteFreeEdges(const TopoDS_Shape& theSewShape, 
263                                         TopTools_MapOfShape& theMapEdges,
264                                         TopoDS_Compound& theNewComp) const
265 {
266  
267   BRep_Builder aB;
268   aB.MakeCompound(theNewComp);
269   TopoDS_Iterator aIt(theSewShape);
270   
271   for( ; aIt.More(); aIt.Next()) {
272     if((aIt.Value().ShapeType() == TopAbs_EDGE ) && theMapEdges.Contains(aIt.Value()))
273       continue;
274     else if(aIt.Value().ShapeType() == TopAbs_COMPOUND) {
275       TopoDS_Compound aC;
276       deleteFreeEdges(aIt.Value(),theMapEdges,aC);
277       aB.Add(theNewComp,aC);
278     }
279     else
280       aB.Add(theNewComp,aIt.Value());
281   }
282 }