Salome HOME
Merge remote-tracking branch 'origin/master' into rnc/t_shape_plugin
[modules/geom.git] / src / AdvancedEngine / AdvancedEngine_PipeTShapeDriver.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "AdvancedEngine_PipeTShapeDriver.hxx"
21 #include "AdvancedEngine_IPipeTShape.hxx"
22 #include "AdvancedEngine_Types.hxx"
23 #include "AdvancedEngine_IOperations.hxx"
24
25 #include "GEOMImpl_Block6Explorer.hxx"
26 #include "GEOM_Function.hxx"
27 #include "GEOM_IOperations.hxx"
28 #include "GEOMUtils.hxx"
29 #include "GEOMAlgo_FinderShapeOn1.hxx"
30 #include "GEOMAlgo_FinderShapeOn2.hxx"
31 #include "GEOMAlgo_ClsfBox.hxx"
32 #include "GEOMAlgo_Splitter.hxx"
33
34 #include "Geom_CylindricalSurface.hxx"
35 #include <gp_Pnt.hxx>
36 #include <gp_Vec.hxx>
37 #include <gp_Ax2.hxx>
38 #include <gp_Pln.hxx>
39 #include <gp_Dir.hxx>
40 #include <gp_Trsf.hxx>
41 #include <TFunction_Logbook.hxx>
42 #include <StdFail_NotDone.hxx>
43 #include <BRepPrimAPI_MakeCone.hxx>
44 #include <BRepPrimAPI_MakeCylinder.hxx>
45 #include <BRepAlgoAPI_Fuse.hxx>
46 #include <BRepAlgoAPI_Cut.hxx>
47 #include <BRepPrimAPI_MakeBox.hxx>
48 #include <BRepBuilderAPI_MakeEdge.hxx>
49 #include <BRepBuilderAPI_MakeFace.hxx>
50 #include <BRepBuilderAPI_MakeWire.hxx>
51 #include <BRepBuilderAPI_Transform.hxx>
52 #include <BRepFilletAPI_MakeFillet.hxx>
53 #include <BRepFilletAPI_MakeChamfer.hxx>
54 #include <BRep_Builder.hxx>
55 #include <TopoDS_Compound.hxx>
56 #include <TopExp.hxx>
57 #include <TopExp_Explorer.hxx>
58 #include <BRep_Tool.hxx>
59 #include <BRepTools.hxx>
60 #include <TopoDS.hxx>
61 #include <TopTools_IndexedMapOfShape.hxx>
62 #include <TopTools_ListIteratorOfListOfShape.hxx>
63
64 #include <vector>
65
66 //=======================================================================
67 //function : GetID
68 //purpose  :
69 //=======================================================================
70 const Standard_GUID& AdvancedEngine_PipeTShapeDriver::GetID()
71 {
72   static Standard_GUID aGUID("1C3A0F3F-729D-4E83-8232-78E74FC5637C");
73   return aGUID;
74 }
75
76 //=======================================================================
77 //function : AdvancedEngine_PipeTShapeDriver
78 //purpose  :
79 //=======================================================================
80 AdvancedEngine_PipeTShapeDriver::AdvancedEngine_PipeTShapeDriver()
81 {
82 }
83
84 //=======================================================================
85 //function : getShapesOnBoxIDs
86   /*!
87    * \brief Find IDs of sub-shapes complying with given status about surface
88     * \param theBox - the box to check state of sub-shapes against
89     * \param theShape - the shape to explore
90     * \param theShapeType - type of sub-shape of theShape
91     * \param theState - required state
92     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
93    */
94 //=======================================================================
95 Handle(TColStd_HSequenceOfInteger)
96 AdvancedEngine_PipeTShapeDriver::GetShapesOnBoxIDs(const TopoDS_Shape& aBox,
97                     const TopoDS_Shape& aShape,
98                     const Standard_Integer theShapeType,
99                     GEOMAlgo_State theState) const
100 {
101   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
102
103   // Check presence of triangulation, build if need
104   if (!GEOMUtils::CheckTriangulation(aShape)) {
105     StdFail_NotDone::Raise("Cannot build triangulation on the shape");
106     return aSeqOfIDs;
107   }
108
109   // Call algo
110   GEOMAlgo_FinderShapeOn2 aFinder;
111   Standard_Real aTol = 0.0001; // default value
112
113   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
114   aClsfBox->SetBox(aBox);
115
116   aFinder.SetShape(aShape);
117   aFinder.SetTolerance(aTol);
118   aFinder.SetClsf(aClsfBox);
119   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
120   aFinder.SetState(theState);
121   aFinder.Perform();
122
123   // Interprete results
124   Standard_Integer iErr = aFinder.ErrorStatus();
125   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
126   if (iErr) {
127     TCollection_AsciiString aMsg (" iErr : ");
128     aMsg += TCollection_AsciiString(iErr);
129     StdFail_NotDone::Raise(aMsg.ToCString());
130     return aSeqOfIDs;
131   }
132
133
134   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
135
136   if (listSS.Extent() < 1) {
137     StdFail_NotDone::Raise(NOT_FOUND_ANY); // NPAL18017
138     return aSeqOfIDs;
139   }
140
141   // Fill sequence of object IDs
142   aSeqOfIDs = new TColStd_HSequenceOfInteger;
143
144   TopTools_IndexedMapOfShape anIndices;
145   TopExp::MapShapes(aShape, anIndices);
146
147   TopTools_ListIteratorOfListOfShape itSub (listSS);
148   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
149     int id = anIndices.FindIndex(itSub.Value());
150 //    std::cerr << "Shape with ID " << id << " found" << std::endl;
151     aSeqOfIDs->Append(id);
152   }
153
154   return aSeqOfIDs;
155 }
156
157 //=======================================================================
158 //function : GetShapesOnSurfaceIDs
159   /*!
160    * \brief Find IDs of sub-shapes complying with given status about surface
161     * \param theSurface - the surface to check state of sub-shapes against
162     * \param theShape - the shape to explore
163     * \param theShapeType - type of sub-shape of theShape
164     * \param theState - required state
165     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
166    */
167 //=======================================================================
168 Handle(TColStd_HSequenceOfInteger)
169   AdvancedEngine_PipeTShapeDriver::GetShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
170                                                     const TopoDS_Shape&         theShape,
171                                                     TopAbs_ShapeEnum            theShapeType,
172                                                     GEOMAlgo_State              theState) const
173 {
174   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
175
176   // Check presence of triangulation, build if need
177   if (!GEOMUtils::CheckTriangulation(theShape)) {
178     StdFail_NotDone::Raise("Cannot build triangulation on the shape");
179     return aSeqOfIDs;
180   }
181
182   // Call algo
183   GEOMAlgo_FinderShapeOn1 aFinder;
184   Standard_Real aTol = 1e-6;
185
186   aFinder.SetShape(theShape);
187   aFinder.SetTolerance(aTol);
188   aFinder.SetSurface(theSurface);
189   aFinder.SetShapeType(theShapeType);
190   aFinder.SetState(theState);
191
192   // Sets the minimal number of inner points for the faces that do not have own
193   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
194   // Default value=3
195   aFinder.SetNbPntsMin(3);
196   // Sets the maximal number of inner points for edges or faces.
197   // It is usefull for the cases when this number is very big (e.g =2000) to improve
198   // the performance. If this value =0, all inner points will be taken into account.
199   // Default value=0
200   aFinder.SetNbPntsMax(0);
201
202   aFinder.Perform();
203
204   // Interprete results
205   Standard_Integer iErr = aFinder.ErrorStatus();
206   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
207   if (iErr) {
208 //    MESSAGE(" iErr : " << iErr);
209     TCollection_AsciiString aMsg (" iErr : ");
210     aMsg += TCollection_AsciiString(iErr);
211     StdFail_NotDone::Raise(aMsg.ToCString());
212     return aSeqOfIDs;
213   }
214 //  Standard_Integer iWrn = aFinder.WarningStatus();
215   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
216 //  if (iWrn) {
217 //    MESSAGE(" *** iWrn : " << iWrn);
218 //  }
219
220   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
221
222   if (listSS.Extent() < 1) {
223     //StdFail_NotDone::Raise("Not a single sub-shape of the requested type found on the given surface");
224     StdFail_NotDone::Raise(NOT_FOUND_ANY); // NPAL18017
225     return aSeqOfIDs;
226   }
227
228   // Fill sequence of object IDs
229   aSeqOfIDs = new TColStd_HSequenceOfInteger;
230
231   TopTools_IndexedMapOfShape anIndices;
232   TopExp::MapShapes(theShape, anIndices);
233
234   TopTools_ListIteratorOfListOfShape itSub (listSS);
235   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
236     int id = anIndices.FindIndex(itSub.Value());
237     aSeqOfIDs->Append(id);
238   }
239
240   return aSeqOfIDs;
241 }
242
243 //=======================================================================
244 //function : GetCommonShapesOnCylinders
245 //purpose  : return the common shapes between 2 cylindrical surfaces
246 //           along OX and OZ
247 //=======================================================================
248 void AdvancedEngine_PipeTShapeDriver::GetCommonShapesOnCylinders(const TopoDS_Shape& theShape,
249                                                            TopAbs_ShapeEnum theShapeType,
250                                                            double r1,
251                                                            double r2,
252                                                            Handle(TopTools_HSequenceOfShape)& commonShapes) const
253 {
254   gp_Pnt aP0 (0, 0, 0);
255   gp_Vec aVX = gp::DX(), aVZ = gp::DZ();
256   gp_Ax3 anAxis1 (aP0, aVX, aVZ), anAxis2 (aP0, aVZ, aVX);
257
258   TopTools_IndexedMapOfShape aMapOfShapes;
259   aMapOfShapes.Clear();
260   TopExp::MapShapes(theShape, aMapOfShapes);
261
262   commonShapes->Clear();
263
264   int myID;
265   bool found = false;
266
267   // Create a cylinder surface
268   Handle(Geom_Surface) aC1Ext = new Geom_CylindricalSurface(anAxis1, r1);
269   if ( aC1Ext.IsNull() )
270     StdFail_NotDone::Raise("Couldn't build main cylindrical surface");
271   // Find object IDs
272   Handle(TColStd_HSequenceOfInteger) aSeqExt1 = GetShapesOnSurfaceIDs( aC1Ext, theShape, theShapeType, GEOMAlgo_ST_ON );
273   // Create a cylinder surface
274   Handle(Geom_Surface) aC2Ext = new Geom_CylindricalSurface(anAxis2, r2);
275   if ( aC2Ext.IsNull() )
276     StdFail_NotDone::Raise("Couldn't build incident cylindrical surface");
277   // Find object IDs
278   Handle(TColStd_HSequenceOfInteger) aSeqExt2 = GetShapesOnSurfaceIDs( aC2Ext, theShape, theShapeType, GEOMAlgo_ST_ON );
279   // # Recherche (dans le quart de Te) de l'arete d'intersection des 2 cylindres
280   // # Search in theShape for common shape of type theShapeType on the intersection of 2 pipes
281   found = false;
282   for (int i=1; i<=aSeqExt2->Length();i++) {
283 //    std::cerr << "aSeqExt2->Value(i): " << aSeqExt2->Value(i) << std::endl;
284     for (int j=1; j<=aSeqExt1->Length();j++) {
285 //      std::cerr << "aSeqExt1->Value(j): " << aSeqExt1->Value(j) << std::endl;
286       if (aSeqExt1->Value(j) == aSeqExt2->Value(i)) {
287         myID = aSeqExt1->Value(j);
288         commonShapes->Append(aMapOfShapes.FindKey(myID));
289         found = true;
290       }
291     }
292   }
293   if (!found)
294     StdFail_NotDone::Raise("Common shapes couldn't be found");
295 }
296
297 //=======================================================================
298 //function : MakePipeTShape
299 //purpose  :
300 //=======================================================================
301 TopoDS_Shape AdvancedEngine_PipeTShapeDriver::MakePipeTShape (const double r1, const double w1, const double l1,
302                                                         const double r2, const double w2, const double l2) const
303 {
304   double r1Ext = r1 + w1;
305   double r2Ext = r2 + w2;
306
307   gp_Pnt aP0 (0, 0, 0);
308   gp_Pnt aP1 (-l1, 0, 0);
309   gp_Vec aVX = gp::DX(), aVY = gp::DY(), aVZ = gp::DZ();
310   gp_Ax2 anAxes1 (aP1, aVX, aVZ);
311   gp_Ax2 anAxes2 (aP0, aVZ, aVX);
312
313   // Build the initial pipes
314   BRepPrimAPI_MakeCylinder C1Int (anAxes1, r1, Abs(2 * l1));
315   BRepPrimAPI_MakeCylinder C1Ext (anAxes1, r1Ext, Abs(2 * l1));
316   BRepPrimAPI_MakeCylinder C2Int (anAxes2, r2, Abs(l2));
317   BRepPrimAPI_MakeCylinder C2Ext (anAxes2, r2Ext, Abs(l2));
318   C1Int.Build();
319   C1Ext.Build();
320   C2Int.Build();
321   C2Ext.Build();
322   if (!C1Int.IsDone() || !C1Ext.IsDone() || !C2Int.IsDone() || !C2Ext.IsDone()) {
323     StdFail_NotDone::Raise("Cannot build cylinders");
324   }
325
326   // Fuse the 2 pipes
327   BRepAlgoAPI_Fuse fuse1 (C1Ext.Shape(), C2Ext.Shape());
328   if (!fuse1.IsDone()) {
329     StdFail_NotDone::Raise("Cannot fuse cylinders");
330   }
331
332   // Remove small radius main pipe
333   BRepAlgoAPI_Cut cut1 (fuse1.Shape(), C1Int.Shape());
334   if (!cut1.IsDone()) {
335     StdFail_NotDone::Raise("Coudn't cut cylinders");
336   }
337
338   // Remove small radius incident pipe => Te
339   BRepAlgoAPI_Cut Te (cut1.Shape(), C2Int.Shape());
340   if (!Te.IsDone()) {
341     StdFail_NotDone::Raise("Coudn't cut cylinders");
342   }
343
344   return Te.Shape();
345 }
346
347 //=======================================================================
348 //function : MakeQuarterPipeTShape
349 //purpose  :
350 //=======================================================================
351 TopoDS_Shape AdvancedEngine_PipeTShapeDriver::MakeQuarterPipeTShape (const double r1, const double w1, const double l1,
352                                                                const double r2, const double w2, const double l2) const
353 {
354   TopoDS_Shape Te = MakePipeTShape(r1, w1, l1, r2, w2, l2);
355   if (Te.IsNull())
356     StdFail_NotDone::Raise("Couldn't build Pipe TShape");
357
358   // Get a quarter of shape => Te2
359   double r1Ext = r1 + w1;
360   BRepPrimAPI_MakeBox box1 (gp_Pnt(0, -2*r1Ext, -2*r1Ext), gp_Pnt( Abs(2 * l1), 2*r1Ext, Abs(2*l2)));
361   BRepPrimAPI_MakeBox box2 (gp_Pnt(0,  2*r1Ext, -2*r1Ext), gp_Pnt(-Abs(2 * l1), 0,       Abs(2*l2)));
362   box1.Build();
363   box2.Build();
364   if (!box1.IsDone() || !box2.IsDone()) {
365     StdFail_NotDone::Raise("Couldn't build boxes");
366   }
367   BRepAlgoAPI_Cut cut3 (Te, box1.Shape());
368   if (!cut3.IsDone()) {
369     StdFail_NotDone::Raise("Couldn't cut Pipe Tshape with box");
370   }
371   BRepAlgoAPI_Cut Te4 (cut3.Shape(), box2.Shape());
372   if (!Te4.IsDone()) {
373     StdFail_NotDone::Raise("Couldn't cut Pipe Tshape with box");
374   }
375
376   return Te4.Shape();
377 }
378
379 //=======================================================================
380 //function : Execute
381 //purpose  :
382 //=======================================================================
383 Standard_Integer AdvancedEngine_PipeTShapeDriver::Execute (TFunction_Logbook& log) const
384 {
385   if (Label().IsNull()) return 0;
386   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
387
388   AdvancedEngine_IPipeTShape aData (aFunction);
389   Standard_Integer aType = aFunction->GetType();
390
391   TopoDS_Shape aShape, Te4, Te4Part;
392   //TopoDS_Edge arete_intersect_int;
393   //Handle(TopTools_HSequenceOfShape) edges_e = new TopTools_HSequenceOfShape;
394   Handle(TColStd_HSequenceOfInteger) edges_e;
395   //Handle(TopTools_HSequenceOfShape) edges_i = new TopTools_HSequenceOfShape;
396   //gp_Pnt aP0 (0, 0, 0);
397   //gp_Vec aVX = gp::DX(), aVY = gp::DY(), aVZ = gp::DZ();
398   bool hexMesh = (bool) aData.GetHexMesh();
399
400   // Useful values
401   //double aSize = 2*(aData.GetL1() + aData.GetL2());
402   double epsilon = Precision::Approximation();
403   double aR1Ext = aData.GetR1() + aData.GetW1();
404   double aR2Ext = aData.GetR2() + aData.GetW2();
405
406   if (aData.GetR2() > aData.GetR1() + epsilon) {
407     StdFail_NotDone::Raise("TShape cannot be computed if R2 > R1");
408   }
409
410   if (aR2Ext > aR1Ext + epsilon) {
411     StdFail_NotDone::Raise("TShape cannot be computed if R2+W2 > R1+W1");
412   }
413
414   // external radius are equal
415   if (fabs(aR2Ext - aR1Ext) < epsilon) {
416     if (aType == TSHAPE_CHAMFER)
417       StdFail_NotDone::Raise("TShape with chamfer cannot be computed if R2+W2 = R1+W1");
418     if (aType == TSHAPE_FILLET)
419       StdFail_NotDone::Raise("TShape with fillet cannot be computed if R2+W2 = R1+W1");
420     // internal radius are different => not possible
421     if (fabs(aData.GetR2() - aData.GetR1()) > epsilon) {
422       StdFail_NotDone::Raise("TShape cannot be computed if R2+W2 = R1+W1 and R2 != R1");
423     }
424   }
425
426   if (aR1Ext >= aData.GetL2() + epsilon) {
427     StdFail_NotDone::Raise("TShape cannot be computed if R1+W1 >= L2");
428   }
429   if (aR2Ext >= aData.GetL1() + epsilon) {
430     StdFail_NotDone::Raise("TShape cannot be computed if R2+W2 >= L1");
431   }
432
433   if (aType == TSHAPE_CHAMFER) {
434     if (aData.GetH() >= (aData.GetL2() - aR1Ext + epsilon)) {
435       StdFail_NotDone::Raise("TShape cannot be computed: height of chamfer is too high");
436     }
437
438     if (aData.GetW() >= (aData.GetL1() - aR2Ext + epsilon))
439       StdFail_NotDone::Raise("TShape cannot be computed: width of chamfer is too high");
440   }
441
442   if (aType == TSHAPE_FILLET) {
443     if (aData.GetRF() >= (aData.GetL2() - aR1Ext + epsilon) ||
444         aData.GetRF() >= (aData.GetL1() - aR2Ext + epsilon))
445       StdFail_NotDone::Raise("TShape cannot be computed: radius of fillet is too high");
446   }
447
448   if (hexMesh) {
449     // Create a quarter of a basic T-Shape pipe
450     //std::cerr << "Create a quarter of a basic T-Shape pipe" << std::endl;
451     Te4 = MakeQuarterPipeTShape(aData.GetR1(), aData.GetW1(), aData.GetL1(),
452                                 aData.GetR2(), aData.GetW2(), aData.GetL2());
453   }
454   else {
455     // No need to cut pipe t-shape
456     //std::cerr << "Create a basic T-Shape pipe" << std::endl;
457     Te4 = MakePipeTShape(aData.GetR1(), aData.GetW1(), aData.GetL1(),
458                          aData.GetR2(), aData.GetW2(), aData.GetL2());
459   }
460   aShape = Te4;
461 /*
462   if (aType == TSHAPE_BASIC) {
463       aShape = Te4;
464 //       aShape = MakeQuarterPipeTShape(aData.GetR1(), aData.GetW1(), aData.GetL1(),
465 //       aData.GetR2(), aData.GetW2(), aData.GetL2());
466   }
467   else if (aType == TSHAPE_CHAMFER) {
468     // TShape with chamfer
469 //     BRep_Builder BB;
470 //     TopoDS_Compound CC;
471 //     BB.MakeCompound(CC);
472     // Create chamfer on the edges edges_e
473     BRepFilletAPI_MakeChamfer chamfer (Te4);
474     TopTools_IndexedMapOfShape anEdgesIndices;
475     TopExp::MapShapes(Te4, anEdgesIndices);
476
477     TopoDS_Shape theBox;
478     if (hexMesh) {
479       BRepPrimAPI_MakeBox aBox (gp_Pnt(0,0,0),gp_Pnt(-aR2Ext, -aR2Ext, aR1Ext));
480       aBox.Build();
481       if (!aBox.IsDone()) {
482         StdFail_NotDone::Raise("Couldn't build box");
483       }
484       theBox = aBox.Shape();
485     }
486     else {
487       BRepPrimAPI_MakeBox aBox (gp_Pnt(aR2Ext,aR2Ext,0),gp_Pnt(-aR2Ext, -aR2Ext, aR1Ext));
488       aBox.Build();
489       if (!aBox.IsDone()) {
490         StdFail_NotDone::Raise("Couldn't build box");
491       }
492       theBox = aBox.Shape();
493     }
494     Handle(TColStd_HSequenceOfInteger) edges_e = new TColStd_HSequenceOfInteger;
495     edges_e = GetShapesOnBoxIDs(theBox, Te4, TopAbs_EDGE, GEOMAlgo_ST_IN);
496     if (edges_e.IsNull() || edges_e->Length() == 0) {
497       StdFail_NotDone::Raise("Common edges not found");
498     }
499
500     TopTools_IndexedDataMapOfShapeListOfShape M;
501     GEOMImpl_Block6Explorer::MapShapesAndAncestors(Te4, TopAbs_EDGE, TopAbs_FACE, M);
502 //     std::cerr << "Number of IDs: " << edges_e->Length() << std::endl;
503     int nbEdgesInChamfer = 0;
504     for (int i=1;i<=edges_e->Length();i++) {
505 //       std::cerr << "Get Edge with ID #" << i << std::endl;
506       int theId = edges_e->Value(i);
507 //       std::cerr << "ID #" << i << "= " << theId << std::endl;
508 //       std::cerr << "Search for edge in shape" << std::endl;
509       TopoDS_Edge theEdge = TopoDS::Edge(anEdgesIndices.FindKey(theId));
510 //       std::cerr << "Found" << std::endl;
511 //       std::cerr << "Keep only edges with a vertex on (x, x, re1)" << std::endl;
512       TopExp_Explorer ExVertices;
513       for (ExVertices.Init(theEdge,TopAbs_VERTEX); ExVertices.More(); ExVertices.Next()) {
514         gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(ExVertices.Current()));
515         if (aPt.Z() - aR1Ext <= epsilon) {
516 //           std::cerr << "aPt.Z() = aR1Ext => keep this edge" << std::endl;
517           nbEdgesInChamfer ++;
518           const TopTools_ListOfShape& aFL = M.FindFromKey(theEdge);
519           TopoDS_Face F = TopoDS::Face( aFL.First() );
520           if (hexMesh)
521             chamfer.Add(aData.GetH(), aData.GetW(), theEdge, F);
522           else
523             chamfer.Add(aData.GetW(), aData.GetH(), theEdge, F);
524           break;
525         }
526       }
527 //       std::cerr << "Test if hexMesh: ";
528       if (hexMesh && nbEdgesInChamfer == 1) {
529 //         std::cerr << "Yes => stop after 1 edge" << std::endl;
530         break;
531       }
532 //       std::cerr << "No => continue for other edges" << std::endl;
533   //  BB.Add(CC, edges_e->Value(i));
534   //  const TopTools_ListOfShape& aFL = M.FindFromKey(TopoDS::Edge(edges_e->Value(i)));
535   //  chamfer.Add(aData.GetW(), aData.GetH(), TopoDS::Edge(edges_e->Value(i)), F);
536     }
537 //     std::cerr << "Build chamfer with " << nbEdgesInChamfer << " edges" << std::endl;
538 //     }
539     chamfer.Build();
540     if (!chamfer.IsDone()) {
541       StdFail_NotDone::Raise("Chamfer can not be computed on the given shape with the given parameters");
542     }
543
544 //     BB.Add(CC, chamfer.Shape());
545
546 //     aShape = CC;
547     aShape = chamfer.Shape();
548   }
549   else if (aType == TSHAPE_FILLET) {
550     // TShape with fillet
551     // Create fillet on the edge arete_intersect_ext
552     BRepFilletAPI_MakeFillet fill (Te4);
553
554     TopTools_IndexedMapOfShape anIndices;
555     TopExp::MapShapes(Te4, anIndices);
556
557     TopoDS_Shape theBox;
558     if (hexMesh) {
559       BRepPrimAPI_MakeBox aBox (gp_Pnt(0,0,0),gp_Pnt(-aR2Ext, -aR2Ext, aR1Ext));
560       aBox.Build();
561       if (!aBox.IsDone()) {
562         StdFail_NotDone::Raise("Couldn't build box");
563       }
564       theBox = aBox.Shape();
565     }
566     else {
567       BRepPrimAPI_MakeBox aBox (gp_Pnt(aR2Ext,aR2Ext,0),gp_Pnt(-aR2Ext, -aR2Ext, aR1Ext));
568       aBox.Build();
569       if (!aBox.IsDone()) {
570         StdFail_NotDone::Raise("Couldn't build box");
571       }
572       theBox = aBox.Shape();
573     }
574     Handle(TColStd_HSequenceOfInteger) edges_e = new TColStd_HSequenceOfInteger;
575     edges_e = GetShapesOnBoxIDs(theBox, Te4, TopAbs_EDGE, GEOMAlgo_ST_IN);
576     if (edges_e.IsNull() || edges_e->Length() == 0) {
577       StdFail_NotDone::Raise("Common edges not found");
578     }
579
580 //     fill.Add(TopoDS::Edge(edges_e->Value(1)));
581 //     if (!hexMesh) {
582     for (int i=1;i<=edges_e->Length();i++) {
583       if (hexMesh && (i > 1))
584         break;
585       TopoDS_Edge theEdge = TopoDS::Edge(anIndices.FindKey(edges_e->Value(i)));
586       fill.Add(theEdge);
587 //             fill.Add(TopoDS::Edge(edges_e->Value(i)));
588     }
589 //     }
590     fill.SetRadius(aData.GetRF(), 1, 1);
591     fill.Build();
592     if (!fill.IsDone()) {
593       StdFail_NotDone::Raise("Fillet can't be computed on the given shape with the given radius");
594     }
595
596     aShape = fill.Shape();
597   }
598   else {
599     // other construction modes here
600   }
601 */
602   if (aShape.IsNull()) return 0;
603
604   aFunction->SetValue(aShape);
605
606   log.SetTouched(Label());
607
608   return 1;
609 }
610
611 //================================================================================
612 /*!
613  * \brief Returns a name of creation operation and names and values of creation parameters
614  */
615 //================================================================================
616
617 bool AdvancedEngine_PipeTShapeDriver::
618 GetCreationInformation(std::string&             theOperationName,
619                        std::vector<GEOM_Param>& theParams)
620 {
621   if (Label().IsNull()) return 0;
622   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
623
624   AdvancedEngine_IPipeTShape aCI( function );
625   Standard_Integer aType = function->GetType();
626
627   theOperationName = "PIPETSHAPE";
628
629   switch ( aType ) {
630   case TSHAPE_BASIC:
631     AddParam( theParams, "Main radius", aCI.GetR1() );
632     AddParam( theParams, "Main width", aCI.GetW1() );
633     AddParam( theParams, "Main half-length", aCI.GetL1() );
634     AddParam( theParams, "Incident pipe radius", aCI.GetR2() );
635     AddParam( theParams, "Incident pipe width", aCI.GetW2() );
636     AddParam( theParams, "Incident pipe half-length", aCI.GetL2() );
637     AddParam( theParams, "For hex mesh", aCI.GetHexMesh() );
638     break;
639   case TSHAPE_CHAMFER:
640     AddParam( theParams, "Main radius", aCI.GetR1() );
641     AddParam( theParams, "Main width", aCI.GetW1() );
642     AddParam( theParams, "Main half-length", aCI.GetL1() );
643     AddParam( theParams, "Incident pipe radius", aCI.GetR2() );
644     AddParam( theParams, "Incident pipe width", aCI.GetW2() );
645     AddParam( theParams, "Incident pipe half-length", aCI.GetL2() );
646     AddParam( theParams, "Chamfer height", aCI.GetH() );
647     AddParam( theParams, "Chamfer width", aCI.GetW() );
648     AddParam( theParams, "For hex mesh", aCI.GetHexMesh() );
649     break;
650   case TSHAPE_FILLET:
651     AddParam( theParams, "Main radius", aCI.GetR1() );
652     AddParam( theParams, "Main width", aCI.GetW1() );
653     AddParam( theParams, "Main half-length", aCI.GetL1() );
654     AddParam( theParams, "Incident pipe radius", aCI.GetR2() );
655     AddParam( theParams, "Incident pipe width", aCI.GetW2() );
656     AddParam( theParams, "Incident pipe half-length", aCI.GetL2() );
657     AddParam( theParams, "Fillet radius", aCI.GetRF() );
658     AddParam( theParams, "For hex mesh", aCI.GetHexMesh() );
659     break;
660   default:
661     return false;
662   }
663   
664   return true;
665 }
666
667 IMPLEMENT_STANDARD_HANDLE (AdvancedEngine_PipeTShapeDriver,GEOM_BaseDriver);
668 IMPLEMENT_STANDARD_RTTIEXT (AdvancedEngine_PipeTShapeDriver,GEOM_BaseDriver);