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