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