Salome HOME
fedb7af9b5533146a119a16ff02973e16efdc6ea
[modules/geom.git] / src / GEOMImpl / GEOMImpl_GlueDriver.cxx
1
2 using namespace std;
3 #include "GEOMImpl_GlueDriver.hxx"
4 #include "GEOMImpl_IGlue.hxx"
5 #include "GEOMImpl_Types.hxx"
6 #include "GEOM_Function.hxx"
7
8 #include <BRep_Tool.hxx>
9 #include <BRep_Builder.hxx>
10 #include <BRepLib.hxx>
11 #include <BRepTools_Quilt.hxx>
12 #include <BRepClass3d_SolidClassifier.hxx>
13
14 #include <TopExp.hxx>
15 #include <TopExp_Explorer.hxx>
16 #include <TopAbs.hxx>
17 #include <TopoDS.hxx>
18 #include <TopoDS_Shape.hxx>
19 #include <TopoDS_Face.hxx>
20 #include <TopoDS_Edge.hxx>
21 #include <TopoDS_Vertex.hxx>
22 #include <TopoDS_Compound.hxx>
23 #include <TopoDS_Shell.hxx>
24 #include <TopoDS_Solid.hxx>
25 #include <TopTools_ListOfShape.hxx>
26 #include <TopTools_ListIteratorOfListOfShape.hxx>
27
28 #include <gp_Pnt.hxx>
29 #include <Precision.hxx>
30 #include <Standard_NullObject.hxx>
31 #include <Standard_ConstructionError.hxx>
32
33 //=======================================================================
34 //function : GetID
35 //purpose  :
36 //=======================================================================
37 const Standard_GUID& GEOMImpl_GlueDriver::GetID()
38 {
39   static Standard_GUID aGlueDriver("FF1BBB63-5D14-4df2-980B-3A668264EA16");
40   return aGlueDriver;
41 }
42
43
44 //=======================================================================
45 //function : GEOMImpl_GlueDriver
46 //purpose  :
47 //=======================================================================
48 GEOMImpl_GlueDriver::GEOMImpl_GlueDriver()
49 {
50 }
51
52 //=======================================================================
53 //function : FindSameFace
54 //purpose  : for GLUE_FACES
55 //=======================================================================
56 static TopoDS_Face FindSameFace (const TopoDS_Shape& aShape,
57                                  const TopoDS_Face& F,
58                                  double tol3d)
59 {
60   TopoDS_Face aFace;
61   bool isSame = false;
62   for (TopExp_Explorer exf (aShape, TopAbs_FACE); exf.More(); exf.Next()) {
63     // test a face
64     int nbFound = 0;
65     aFace = TopoDS::Face(exf.Current());
66     TopTools_ListOfShape liste1;
67     TopTools_ListOfShape liste2;
68     for (TopExp_Explorer exp (aFace, TopAbs_VERTEX); exp.More(); exp.Next()) {
69       const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
70       liste1.Append(V);
71     }
72     for (TopExp_Explorer exp (F, TopAbs_VERTEX); exp.More(); exp.Next()) {
73       const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
74       liste2.Append(V);
75     }
76     isSame = false;
77     if (liste1.Extent() == liste2.Extent())
78     {
79       TopTools_ListIteratorOfListOfShape it1 (liste1);
80       isSame = true;
81       for (; it1.More(); it1.Next())
82       {
83         bool foundSamePoint = false;
84         gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1.Value()));
85         TopTools_ListIteratorOfListOfShape it2 (liste2);
86         for (; it2.More(); it2.Next()) {
87           gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2.Value()));
88           double d = P1.Distance(P2);
89           if (d < tol3d) {
90             nbFound++;
91             // found Same Point : P1
92             foundSamePoint = true;
93             break;
94           }
95         }
96         isSame = isSame && foundSamePoint;
97         if (! isSame) break; // a vertex does not correspond : not same face
98       }
99     }
100     if (isSame) {
101       // Found Same Face
102       break; // a face corresponding to F is found
103     }
104   }
105   if (!isSame) aFace.Nullify(); // return null face
106   return aFace;
107 }
108
109 //=======================================================================
110 //function : FindSameEdge
111 //purpose  : for GLUE_FACES
112 //=======================================================================
113 static TopoDS_Edge FindSameEdge (const TopoDS_Face& nf, TopoDS_Edge& Eold,
114                                  double tol3d)
115 {
116   TopoDS_Face newFace = TopoDS::Face(nf.Oriented(TopAbs_REVERSED));
117   TopoDS_Vertex VFirst, VLast;
118   TopExp::Vertices(Eold, VFirst, VLast);
119   gp_Pnt Pf = BRep_Tool::Pnt(VFirst);
120   gp_Pnt Pl = BRep_Tool::Pnt(VLast);
121   TopoDS_Edge Enew;
122   for (TopExp_Explorer ee (newFace, TopAbs_EDGE); ee.More(); ee.Next()) {
123     const TopoDS_Edge& E = TopoDS::Edge(ee.Current());
124     TopoDS_Vertex VFn, VLn;
125     TopExp::Vertices(E, VFn, VLn);
126     gp_Pnt Pfn = BRep_Tool::Pnt(VFn);
127     gp_Pnt Pln = BRep_Tool::Pnt(VLn);
128     double dff = Pf.Distance(Pfn);
129     double dfl = Pf.Distance(Pln);
130     double dlf = Pl.Distance(Pfn);
131     double dll = Pl.Distance(Pln);
132     if ((dff < tol3d) && (dll <tol3d)) {
133       // edge forward : Pf - Pl
134       Enew = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
135       Eold = TopoDS::Edge(Eold.Oriented(TopAbs_FORWARD));
136       break;
137     }
138     if ((dfl < tol3d) && (dlf <tol3d)) {
139       // edge reversed : Pf - Pl
140       Enew = TopoDS::Edge(E.Oriented(TopAbs_REVERSED));
141       Eold = TopoDS::Edge(Eold.Oriented(TopAbs_FORWARD));
142       break;
143     }
144   }
145   return Enew;
146 }
147
148 //=======================================================================
149 //function : GlueFaces
150 //purpose  :
151 //=======================================================================
152 TopoDS_Shape GEOMImpl_GlueDriver::GlueFaces (const TopoDS_Shape& theShape,
153                                              const Standard_Real theTolerance)
154 {
155   // prendre un premier shell dans la liste des shells
156   // initialiser un compshell avec ce shell
157   // tant qu'il reste des shells dans la liste
158   //   chercher un shell qui a des faces en  commun avec le compshell
159   //   creer un BRepTools_Quilt
160   //   recenser les faces communes issues du compshell, les ajouter au quilt
161   //   recenser les faces restantes du shell a inclure, les ajouter au quilt
162   //   recenser les edges en double, a remplacer
163   //   pour chaque paire d'edge
164   //     tester l'orientation relative des aretes
165   //     bind dans le quilt de Eold.Forward et Enew.Forward (ou reverse)
166   //   recuperer le nouveau shell
167   // l'incorporer dans le compshell
168   // appliquer BRepTools_SameParameter au compshell
169   // (rendre parametres 2D des edges identiques aux parametres 3D)
170
171   TopoDS_Shape aShape;
172
173   TopoDS_Compound C;
174   BRep_Builder bu;
175   bu.MakeCompound(C); // empty compound;
176   TopTools_ListOfShape shellList;
177   for (TopExp_Explorer exp (theShape, TopAbs_SHELL); exp.More(); exp.Next()) {
178     const TopoDS_Shell& S = TopoDS::Shell(exp.Current());
179     shellList.Append(S);
180   }
181   TopTools_ListIteratorOfListOfShape its (shellList);
182   if (!its.More()) {
183     Standard_ConstructionError::Raise("Glue aborted : no shell in shape");
184   }
185   TopoDS_Shell S = TopoDS::Shell(its.Value());
186   bu.Add(C, S); // add first shell to compound
187   shellList.Remove(its);
188   bool shellAdded = true;
189   while ((shellList.Extent() > 0) && shellAdded) {
190     shellAdded = false;
191     its.Initialize(shellList);
192     for (; its.More(); its.Next()) {
193       TopTools_ListOfShape newFaces; // common faces from new compound
194       TopTools_ListOfShape oldFaces; // common faces from shell to add
195       TopTools_ListOfShape addFaces; // not common faces from shell to add
196       TopTools_ListOfShape newEdges; // common edges from new compound
197       TopTools_ListOfShape oldEdges; // common edges from face to add
198       TopoDS_Compound CFN;
199       TopoDS_Compound CFO;
200       bu.MakeCompound(CFN);       // empty compound for new faces
201       bu.MakeCompound(CFO);       // empty compound for old faces
202       S = TopoDS::Shell(its.Value());
203       for (TopExp_Explorer exp (S, TopAbs_FACE); exp.More(); exp.Next()) {
204         // try to find corresponding face in new compound
205         TopoDS_Face F = TopoDS::Face(exp.Current());
206         TopoDS_Face newFace = FindSameFace(C,F,theTolerance);
207         if (! newFace.IsNull())
208         {
209           // face found
210           newFaces.Append(newFace);
211           bu.Add(CFN, newFace); // common faces from new compound
212           oldFaces.Append(F);
213           for (TopExp_Explorer ee (F, TopAbs_EDGE); ee.More(); ee.Next()) {
214             // find edge pair
215             TopoDS_Edge Eold = TopoDS::Edge(ee.Current());
216             TopoDS_Edge Enew = FindSameEdge(newFace, Eold, theTolerance);
217             if (Enew.IsNull()) {
218               Standard_ConstructionError::Raise("Glue aborted : no same edge in same face");
219             }
220             oldEdges.Append(Eold);
221             newEdges.Append(Enew);
222           }
223         } else {
224           addFaces.Append(F);
225           bu.Add(CFO, F); // not common faces from shell to add
226         }
227       }
228       if (!newFaces.IsEmpty()) {
229         // some faces found
230         shellAdded = true;
231         BRepTools_Quilt glue;
232         glue.Add(CFN);
233         TopTools_ListIteratorOfListOfShape ito (oldEdges);
234         TopTools_ListIteratorOfListOfShape itn (newEdges);
235         for (; ito.More(); ito.Next()) {
236           // bind
237           glue.Bind(TopoDS::Edge(ito.Value()), TopoDS::Edge(itn.Value()));
238           itn.Next();
239         }
240         glue.Add(CFO);
241         TopoDS_Compound newc = TopoDS::Compound(glue.Shells());
242         for (TopExp_Explorer exs (newc, TopAbs_SHELL); exs.More(); exs.Next()) {
243           TopoDS_Shell NS = TopoDS::Shell(exs.Current());
244           bu.Add(C, NS);
245         }
246         shellList.Remove(its);
247         // remove shell from list
248         break;
249       }
250     }
251   }
252
253   TopExp_Explorer exp (C, TopAbs_SHELL);
254   Standard_Integer ish = 0;
255   TopoDS_Compound  Res;
256   TopoDS_Solid     Sol;
257   BRep_Builder     B;
258   B.MakeCompound(Res);
259
260   for (; exp.More(); exp.Next()) {
261     TopoDS_Shape Sh = exp.Current();
262     B.MakeSolid(Sol);
263     B.Add(Sol,Sh);
264     BRepClass3d_SolidClassifier SC(Sol);
265     SC.PerformInfinitePoint(1.E-6); // cf. BRepFill_Confusion() - BRepFill_Evolved.cxx
266     if (SC.State() == TopAbs_IN) {
267       B.MakeSolid(Sol);
268       B.Add(Sol,Sh.Reversed());
269     }
270     B.Add(Res,Sol);
271     ish++;
272   }
273   if (ish == 1) {
274     aShape = Sol;
275   } else {
276     aShape = Res;
277   }
278
279   BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
280   return aShape;
281 }
282
283 //=======================================================================
284 //function : Execute
285 //purpose  :
286 //=======================================================================
287 Standard_Integer GEOMImpl_GlueDriver::Execute(TFunction_Logbook& log) const
288 {
289   if (Label().IsNull()) return 0;
290   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
291
292   GEOMImpl_IGlue aCI (aFunction);
293   Standard_Integer aType = aFunction->GetType();
294
295   TopoDS_Shape aShape;
296
297   if (aType == GLUE_FACES) {
298     Handle(GEOM_Function) aRefBase = aCI.GetBase();
299     TopoDS_Shape aShapeBase = aRefBase->GetValue();
300     if (aShapeBase.IsNull()) {
301       Standard_NullObject::Raise("Shape for gluing is null");
302     }
303
304     Standard_Real tol3d = aCI.GetTolerance();
305     aShape = GlueFaces(aShapeBase, tol3d);
306
307   } else {
308   }
309
310   if (aShape.IsNull()) return 0;
311
312   aFunction->SetValue(aShape);
313
314   log.SetTouched(Label());
315
316   return 1;
317 }
318
319
320 //=======================================================================
321 //function :  GEOMImpl_GlueDriver_Type_
322 //purpose  :
323 //=======================================================================
324 Standard_EXPORT Handle_Standard_Type& GEOMImpl_GlueDriver_Type_()
325 {
326
327   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
328   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
329   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
330   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
331   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
332   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
333
334
335   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
336   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_GlueDriver",
337                                                          sizeof(GEOMImpl_GlueDriver),
338                                                          1,
339                                                          (Standard_Address)_Ancestors,
340                                                          (Standard_Address)NULL);
341
342   return _aType;
343 }
344
345 //=======================================================================
346 //function : DownCast
347 //purpose  :
348 //=======================================================================
349 const Handle(GEOMImpl_GlueDriver) Handle(GEOMImpl_GlueDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
350 {
351   Handle(GEOMImpl_GlueDriver) _anOtherObject;
352
353   if (!AnObject.IsNull()) {
354      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_GlueDriver))) {
355        _anOtherObject = Handle(GEOMImpl_GlueDriver)((Handle(GEOMImpl_GlueDriver)&)AnObject);
356      }
357   }
358
359   return _anOtherObject ;
360 }