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