Salome HOME
Mantis issue 0020998: EDF 1572 GEOM: Some limitations to the PipeTShape.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IAdvancedOperations.cxx
1 //  Copyright (C) 2007-2010  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 //  File   : GEOMImpl_IAdvancedOperations.cxx
20 //  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
21
22 #include <Standard_Stream.hxx>
23 #include "GEOMImpl_Types.hxx"
24 #include "GEOMImpl_IAdvancedOperations.hxx"
25 #include "GEOMImpl_IBasicOperations.hxx"
26 #include "GEOMImpl_IBooleanOperations.hxx"
27 #include "GEOMImpl_IShapesOperations.hxx"
28 #include "GEOMImpl_ITransformOperations.hxx"
29 #include "GEOMImpl_IBlocksOperations.hxx"
30 #include "GEOMImpl_I3DPrimOperations.hxx"
31 #include "GEOMImpl_ILocalOperations.hxx"
32 #include "GEOMImpl_IHealingOperations.hxx"
33
34 #include "GEOMImpl_Gen.hxx"
35
36 #include <utilities.h>
37 #include <OpUtil.hxx>
38 #include <Utils_ExceptHandlers.hxx>
39
40 #include "GEOM_Function.hxx"
41 #include "GEOM_PythonDump.hxx"
42
43 #include "GEOMImpl_PipeTShapeDriver.hxx"
44 #include "GEOMImpl_IPipeTShape.hxx"
45 /*@@ insert new functions before this line @@ do not remove this line @@ do not remove this line @@*/
46
47 #include <TopExp.hxx>
48 #include <TopExp_Explorer.hxx>
49 #include <TopoDS.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopTools_IndexedMapOfShape.hxx>
52
53 #include <gp_Pnt.hxx>
54 #include <gp_Vec.hxx>
55 #include <gp_Ax3.hxx>
56 #include <BRepBuilderAPI_Transform.hxx>
57 #include <BRep_Tool.hxx>
58 #include <BRepTools.hxx>
59 #include <cmath>
60
61 #include <TFunction_DriverTable.hxx>
62 #include <TFunction_Driver.hxx>
63 #include <TFunction_Logbook.hxx>
64 #include <TDF_Tool.hxx>
65 #include <Standard_Failure.hxx>
66 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
67
68 #define HALF_LENGTH_MAIN_PIPE     "Main pipe half length" //"Tuyau principal - demi longueur"
69 #define HALF_LENGTH_INCIDENT_PIPE "Incident pipe half length" //"Tuyau incident - demi longueur"
70 #define CIRCULAR_QUARTER_PIPE     "Circular quarter of pipe" //"Circulaire - quart de tuyau"
71 #define THICKNESS                 "Thickness" //"Epaisseur"
72 #define FLANGE                    "Flange" // "Collerette"
73 #define CHAMFER_OR_FILLET         "Chamfer or fillet" //"Chanfrein ou Raccord"
74 #define JUNCTION_FACE_1           "Junction 1" //"Face de jonction 1"
75 #define JUNCTION_FACE_2           "Junction 2" //"Face de jonction 2"
76 #define JUNCTION_FACE_3           "Junction 3" //"Face de jonction 3"
77
78 //=============================================================================
79 /*!
80  *  Constructor
81  */
82 //=============================================================================
83 GEOMImpl_IAdvancedOperations::GEOMImpl_IAdvancedOperations(GEOM_Engine* theEngine, int theDocID) :
84   GEOM_IOperations(theEngine, theDocID)
85 {
86   MESSAGE("GEOMImpl_IAdvancedOperations::GEOMImpl_IAdvancedOperations");
87   myBasicOperations     = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
88   myBooleanOperations   = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
89   myShapesOperations    = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
90   myTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
91   myBlocksOperations    = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
92   my3DPrimOperations    = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
93   myLocalOperations     = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
94 }
95
96 //=============================================================================
97 /*!
98  *  Destructor
99  */
100 //=============================================================================
101 GEOMImpl_IAdvancedOperations::~GEOMImpl_IAdvancedOperations()
102 {
103   MESSAGE("GEOMImpl_IAdvancedOperations::~GEOMImpl_IAdvancedOperations");
104   delete myBasicOperations;
105   delete myBooleanOperations;
106   delete myShapesOperations;
107   delete myTransformOperations;
108   delete myBlocksOperations;
109   delete my3DPrimOperations;
110   delete myLocalOperations;
111 }
112
113 //=============================================================================
114 /*!
115  *  SetPosition
116  */
117 //=============================================================================
118 gp_Trsf GEOMImpl_IAdvancedOperations::GetPositionTrsf(double theL1, double theL2,
119                                                       Handle(GEOM_Object) theP1,
120                                                       Handle(GEOM_Object) theP2,
121                                                       Handle(GEOM_Object) theP3)
122 {
123   // Old Local Coordinates System oldLCS
124   gp_Pnt P0(0, 0, 0);
125   gp_Pnt P1(-theL1, 0, 0);
126   gp_Pnt P2(theL1, 0, 0);
127   gp_Pnt P3(0, 0, theL2);
128
129   gp_Dir oldX(gp_Vec(P1, P2));
130   gp_Dir oldZ(gp_Vec(P0, P3));
131   gp_Ax3 oldLCS(P0, oldZ, oldX);
132
133   // New Local Coordinates System newLCS
134   double LocX, LocY, LocZ;
135   gp_Pnt newP1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
136   gp_Pnt newP2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
137   gp_Pnt newP3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
138   LocX = (newP1.X() + newP2.X()) / 2.;
139   LocY = (newP1.Y() + newP2.Y()) / 2.;
140   LocZ = (newP1.Z() + newP2.Z()) / 2.;
141   gp_Pnt newO(LocX, LocY, LocZ);
142
143   gp_Dir newX(gp_Vec(newP1, newP2)); // P1P2 Vector
144   gp_Dir newZ(gp_Vec(newO, newP3)); // OP3 Vector
145   gp_Ax3 newLCS = gp_Ax3(newO, newZ, newX);
146
147   gp_Trsf aTrsf;
148   aTrsf.SetDisplacement(oldLCS, newLCS);
149
150   return aTrsf;
151 }
152
153 //=============================================================================
154 /*!
155  *  CheckCompatiblePosition
156  *
157  */
158 //=============================================================================
159 bool GEOMImpl_IAdvancedOperations::CheckCompatiblePosition(double& theL1, double& theL2,
160                                                            Handle(GEOM_Object) theP1,
161                                                            Handle(GEOM_Object) theP2,
162                                                            Handle(GEOM_Object) theP3,
163                                                            double theTolerance)
164 {
165   SetErrorCode(KO);
166   gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
167   gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
168   gp_Pnt P3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
169
170   double d12 = P1.Distance(P2);
171   double d13 = P1.Distance(P3);
172   double d23 = P2.Distance(P3);
173   //    double d2 = newO.Distance(P3);
174
175   if (Abs(d12) <= Precision::Confusion()) {
176     SetErrorCode("Junctions points P1 and P2 are identical");
177     return false;
178   }
179   if (Abs(d13) <= Precision::Confusion()) {
180     SetErrorCode("Junctions points P1 and P3 are identical");
181     return false;
182   }
183   if (Abs(d23) <= Precision::Confusion()) {
184     SetErrorCode("Junctions points P2 and P3 are identical");
185     return false;
186   }
187
188
189   double newL1 = 0.5 * d12;
190   double newL2 = sqrt(pow(d13,2)-pow(newL1,2));
191   //
192   // theL1*(1-theTolerance) <= newL1 <= theL1*(1+theTolerance)
193   //
194   if (fabs(newL1 - theL1) > Precision::Approximation()) {
195     if ( (newL1 * (1 - theTolerance) -theL1 <= Precision::Approximation()) &&
196          (newL1 * (1 + theTolerance) -theL1 >= Precision::Approximation()) ) {
197       //            std::cerr << "theL1 = newL1" << std::endl;
198       theL1 = newL1;
199     } else {
200       theL1 = -1;
201       SetErrorCode("Dimension for main pipe (L1) is incompatible with new position");
202       return false;
203     }
204   }
205
206   //
207   // theL2*(1-theTolerance) <= newL2  <= theL2*(1+theTolerance)
208   //
209   if (fabs(newL2 - theL2) > Precision::Approximation()) {
210     if ( (newL2 * (1 - theTolerance) -theL2 <= Precision::Approximation()) &&
211          (newL2 * (1 + theTolerance) -theL2 >= Precision::Approximation()) ) {
212       theL2 = newL2;
213     } else {
214       theL2 = -1;
215       SetErrorCode("Dimension for incident pipe (L2) is incompatible with new position");
216       return false;
217     }
218   }
219
220   SetErrorCode(OK);
221   return true;
222
223 }
224
225 //=============================================================================
226 /*!
227  *  Generate the propagation groups of a Pipe T-Shape used for hexa mesh
228  */
229 //=============================================================================
230 bool GEOMImpl_IAdvancedOperations::MakeGroups(Handle(GEOM_Object) theShape, int shapeType,
231                                               double theR1, double theW1, double theL1,
232                                               double theR2, double theW2, double theL2,
233                                               Handle(TColStd_HSequenceOfTransient) theSeq,
234                                               gp_Trsf aTrsf)
235 {
236   SetErrorCode(KO);
237
238   if (theShape.IsNull()) return false;
239
240   TopoDS_Shape aShape = theShape->GetValue();
241   if (aShape.IsNull()) {
242     SetErrorCode("Shape is not defined");
243     return false;
244   }
245
246   gp_Trsf aTrsfInv = aTrsf.Inverted();
247
248   int expectedGroups = 0;
249   if (shapeType == TSHAPE_BASIC)
250     if (Abs(theR2+theW2-theR1-theW1) <= Precision::Approximation())
251       expectedGroups = 10;
252     else
253       expectedGroups = 11;
254   else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET)
255     expectedGroups = 12;
256
257   double aR1Ext = theR1 + theW1;
258   double aR2Ext = theR2 + theW2;
259
260   /////////////////////////
261   //// Groups of Faces ////
262   /////////////////////////
263
264   //
265   // Comment the following lines when GetInPlace bug is solved
266   // == BEGIN
267   // Workaround of GetInPlace bug
268   // Create a bounding box that fits the shape
269   Handle(GEOM_Object) aBox = my3DPrimOperations->MakeBoxDXDYDZ(2*theL1, 2*aR1Ext, aR1Ext+theL2);
270   aBox->GetLastFunction()->SetDescription("");
271   myTransformOperations->TranslateDXDYDZ(aBox, -theL1, -aR1Ext, -aR1Ext);
272   aBox->GetLastFunction()->SetDescription("");
273   // Apply transformation to box
274   BRepBuilderAPI_Transform aTransformationBox(aBox->GetValue(), aTrsf, Standard_False);
275   TopoDS_Shape aBoxShapeTrsf = aTransformationBox.Shape();
276   aBox->GetLastFunction()->SetValue(aBoxShapeTrsf);
277
278   // Get the shell of the box
279   Handle(GEOM_Object) aShell = Handle(GEOM_Object)::DownCast
280     (myShapesOperations->MakeExplode(aBox, TopAbs_SHELL, true)->Value(1));
281   aBox->GetLastFunction()->SetDescription("");
282   aShell->GetLastFunction()->SetDescription("");
283   // Get the common shapes between shell and shape
284   Handle(GEOM_Object) aCommonCompound = myBooleanOperations->MakeBoolean (theShape, aShell, 1); // MakeCommon
285   if (aCommonCompound.IsNull()) {
286     SetErrorCode(myBooleanOperations->GetErrorCode());
287     return false;
288   }
289   aCommonCompound->GetLastFunction()->SetDescription("");
290   // Explode the faces of common shapes => 3 faces
291   Handle(TColStd_HSequenceOfTransient) aCommonFaces =
292     myShapesOperations->MakeExplode(aCommonCompound, TopAbs_FACE, true);
293   aCommonCompound->GetLastFunction()->SetDescription("");
294   std::list<Handle(GEOM_Object)> aCompoundOfFacesList;
295
296   for (int i=0 ; i<= aCommonFaces->Length()-4 ; i+=4) {
297     std::list<Handle(GEOM_Object)> aFacesList;
298     for (int j = 1 ; j <= 4 ; j++) {
299       Handle(GEOM_Object) aFace = Handle(GEOM_Object)::DownCast(aCommonFaces->Value(i+j)); // Junction faces
300       if (!aFace.IsNull()) {
301         aFace->GetLastFunction()->SetDescription("");
302         aFacesList.push_back(aFace);
303       }
304     }
305     Handle(GEOM_Object) aCompoundOfFaces = myShapesOperations->MakeCompound(aFacesList);
306     if (!aCompoundOfFaces.IsNull()) {
307       aCompoundOfFaces->GetLastFunction()->SetDescription("");
308       aCompoundOfFacesList.push_back(aCompoundOfFaces);
309     }
310   }
311
312   if (aCompoundOfFacesList.size() == 3) {
313     Handle(GEOM_Object) aPln1 = aCompoundOfFacesList.front();
314     aCompoundOfFacesList.pop_front();
315     Handle(GEOM_Object) aPln2 = aCompoundOfFacesList.front();
316     aCompoundOfFacesList.pop_front();
317     Handle(GEOM_Object) aPln3 = aCompoundOfFacesList.front();
318     aCompoundOfFacesList.pop_front();
319     // == END
320     //
321
322
323     //     Uncomment the following lines when GetInPlace bug is solved
324     //     == BEGIN
325 //     Handle(GEOM_Object) aP1 = myBasicOperations->MakePointXYZ(-theL1, 0, 0);
326 //     Handle(GEOM_Object) aP2 = myBasicOperations->MakePointXYZ(-0, 0, theL2);
327 //     Handle(GEOM_Object) aP3 = myBasicOperations->MakePointXYZ(theL1, 0, 0);
328 //     aP1->GetLastFunction()->SetDescription("");
329 //     aP2->GetLastFunction()->SetDescription("");
330 //     aP3->GetLastFunction()->SetDescription("");
331 //     Handle(GEOM_Object) aV1 = myBasicOperations->MakeVectorDXDYDZ(-1, 0, 0);
332 //     Handle(GEOM_Object) aV2 = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
333 //     Handle(GEOM_Object) aV3 = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
334 //     aV1->GetLastFunction()->SetDescription("");
335 //     aV2->GetLastFunction()->SetDescription("");
336 //     aV3->GetLastFunction()->SetDescription("");
337 //     Handle(GEOM_Object) aPln1 = myBasicOperations->MakePlanePntVec(aP1, aV1, 2*(aR1Ext+theL2));
338 //     Handle(GEOM_Object) aPln2 = myBasicOperations->MakePlanePntVec(aP2, aV2, 2*(aR2Ext));
339 //     Handle(GEOM_Object) aPln3 = myBasicOperations->MakePlanePntVec(aP3, aV3, 2*(aR1Ext+theL2));
340 //     aPln1->GetLastFunction()->SetDescription("");
341 //     aPln2->GetLastFunction()->SetDescription("");
342 //     aPln3->GetLastFunction()->SetDescription("");
343 //
344 //     BRepBuilderAPI_Transform aTransformation1(aPln1->GetValue(), aTrsf, Standard_False);
345 //     TopoDS_Shape aTrsf_Shape1 = aTransformation1.Shape();
346 //     aPln1->GetLastFunction()->SetValue(aTrsf_Shape1);
347 //     BRepBuilderAPI_Transform aTransformation2(aPln2->GetValue(), aTrsf, Standard_False);
348 //     TopoDS_Shape aTrsf_Shape2 = aTransformation2.Shape();
349 //     aPln2->GetLastFunction()->SetValue(aTrsf_Shape2);
350 //     BRepBuilderAPI_Transform aTransformation3(aPln3->GetValue(), aTrsf, Standard_False);
351 //     TopoDS_Shape aTrsf_Shape3 = aTransformation3.Shape();
352 //     aPln3->GetLastFunction()->SetValue(aTrsf_Shape3);
353     //     == END
354     //
355
356     Handle(GEOM_Object) junctionFaces1 = myShapesOperations->GetInPlace(theShape, aPln1);
357     if (junctionFaces1.IsNull())
358       junctionFaces1 = myShapesOperations->GetShapesOnShapeAsCompound
359         (aPln1, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
360     if (!junctionFaces1.IsNull()) {
361       junctionFaces1->GetLastFunction()->SetDescription("");
362       junctionFaces1->SetName("JUNCTION_FACE_1");
363       theSeq->Append(junctionFaces1);
364     }
365     else {
366       SetErrorCode("Junction face 1 not found");
367       //        theSeq->Append(aPln1);
368       //        return false;
369     }
370     Handle(GEOM_Object) junctionFaces2 = myShapesOperations->GetInPlace(theShape, aPln2);
371     if (junctionFaces2.IsNull())
372       junctionFaces2 = myShapesOperations->GetShapesOnShapeAsCompound
373         (aPln2, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
374     if (!junctionFaces2.IsNull()) {
375       junctionFaces2->GetLastFunction()->SetDescription("");
376       junctionFaces2->SetName("JUNCTION_FACE_2");
377       theSeq->Append(junctionFaces2);
378     }
379     else {
380       SetErrorCode("Junction face 2 not found");
381       //        theSeq->Append(aPln2);
382       //        return false;
383     }
384     Handle(GEOM_Object) junctionFaces3 = myShapesOperations->GetInPlace(theShape, aPln3);
385     if (junctionFaces3.IsNull())
386       junctionFaces3 = myShapesOperations->GetShapesOnShapeAsCompound
387         (aPln3, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
388     if (!junctionFaces3.IsNull()) {
389       junctionFaces3->GetLastFunction()->SetDescription("");
390       junctionFaces3->SetName("JUNCTION_FACE_3");
391       theSeq->Append(junctionFaces3);
392     }
393     else {
394       SetErrorCode("Junction face 3 not found");
395       //        theSeq->Append(aPln3);
396       //        return false;
397     }
398   // Comment the following lines when GetInPlace bug is solved
399   // == BEGIN
400   }
401   //     == END
402   /////////////////////////
403   //// Groups of Edges ////
404   /////////////////////////
405   // Result of propagate
406
407   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
408
409   TCollection_AsciiString theDesc = aFunction->GetDescription();
410   Handle(TColStd_HSequenceOfTransient) aSeqPropagate = myBlocksOperations->Propagate(theShape);
411   if (aSeqPropagate.IsNull() || aSeqPropagate->Length() == 0) {
412     SetErrorCode("Propagation groups not found");
413     return false;
414   }
415   Standard_Integer nbEdges, aNbGroups = aSeqPropagate->Length();
416   // Recover previous description to get rid of Propagate dump
417   aFunction->SetDescription(theDesc);
418
419   bool addGroup;
420   bool circularFoundAndAdded = false;
421   bool incidentPipeFound = false;
422   bool mainPipeFound = false;
423   bool mainPipeFoundAndAdded = false;
424   bool radialFound =false;
425   bool flangeFound = false;
426   bool flangeFoundAndAdded = false;
427   bool chamferOrFilletFound = false;
428
429   for (int i=1 ; i<= aNbGroups; i++) {
430     addGroup = false;
431
432     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(aSeqPropagate->Value(i));
433     if(aGroup.IsNull())
434       continue;
435
436     TopoDS_Shape aGroupShape = aGroup->GetValue();
437     BRepBuilderAPI_Transform aTransformationShapeInv(aGroupShape, aTrsfInv, Standard_False);
438     TopoDS_Shape aGroupShapeTrsfInv = aTransformationShapeInv.Shape();
439
440     TopTools_IndexedMapOfShape anEdgesMap;
441     TopExp::MapShapes(aGroupShapeTrsfInv,TopAbs_EDGE, anEdgesMap);
442     nbEdges = anEdgesMap.Extent();
443
444     if (shapeType == TSHAPE_BASIC) {
445       if ((nbEdges == 21) || /*R1Ext = R2Ext*/(nbEdges == 17)){
446         addGroup = true;
447         aGroup->SetName("THICKNESS");
448       }
449       else if (nbEdges == 6) {
450         if (!circularFoundAndAdded) {
451           circularFoundAndAdded = true;
452           addGroup = true;
453           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
454         }
455       }
456       else if (nbEdges == 8) {
457         incidentPipeFound = true;
458         mainPipeFound = false;
459         radialFound =false;
460         flangeFound = false;
461
462         TopExp_Explorer Ex(aGroupShapeTrsfInv,TopAbs_VERTEX);
463         while (Ex.More()) {
464           gp_Pnt aP =  BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
465           double x=aP.X(), y=aP.Y(), z=aP.Z();
466
467
468           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
469               (Abs(y) > aR2Ext + Precision::Confusion())) {
470             incidentPipeFound = false;
471           }
472
473           if ( z < -Precision::Confusion()) {
474             // length of main pipe
475             mainPipeFound = true;
476             if (!mainPipeFoundAndAdded) {
477               mainPipeFoundAndAdded = true;
478               addGroup = true;
479               aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
480             }
481           }
482
483           else if (Abs(x) > (theL1-Precision::Confusion())) {
484             // discretisation circulaire
485             radialFound = true;
486             if (!circularFoundAndAdded) {
487               circularFoundAndAdded = true;
488               addGroup = true;
489               aGroup->SetName("CIRCULAR_QUARTER_PIPE");
490             }
491           }
492           Ex.Next();
493         }
494         if (incidentPipeFound) {
495           addGroup = true;
496           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
497         }
498         if (!addGroup && (!incidentPipeFound &&
499                           !radialFound &&
500                           !mainPipeFound &&
501                           !flangeFound)) {
502           // Flange (collerette)
503           flangeFound = true;
504           addGroup = true;
505           aGroup->SetName("FLANGE");
506         }
507       }
508       else
509         continue;
510     }
511     else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET) {
512       if (nbEdges == 25) {
513         addGroup = true;
514         aGroup->SetName("THICKNESS");
515       }
516       else if ((nbEdges == 10) || (nbEdges == 6)) {
517         if (!circularFoundAndAdded) {
518           addGroup = true;
519           circularFoundAndAdded = true;
520           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
521         }
522       }
523       else if (nbEdges == 8) {
524         incidentPipeFound = true;
525         mainPipeFound = true;
526         flangeFound = false;
527
528         TopExp_Explorer Ex(aGroupShapeTrsfInv,TopAbs_VERTEX);
529         while (Ex.More()) {
530           gp_Pnt aP =  BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
531           double x=aP.X(), y=aP.Y(), z=aP.Z();
532
533           // tuy_princ_long_avant & tuy_princ_long_apres
534           bool isMain = (((z < Precision::Confusion()) || (x < Precision::Confusion())) &&
535                          ((y <= aR1Ext + Precision::Confusion()) ||
536                           (y <= -(aR1Ext + Precision::Confusion())) ||
537                           (y <= theR1 + Precision::Confusion()) ||
538                           (y == -(theR1 + Precision::Confusion()))));
539
540           if (!isMain) {
541             mainPipeFound = false;
542           }
543
544           // collerette
545           if (z < Precision::Confusion()) {
546             flangeFound = true;
547             if (!flangeFoundAndAdded) {
548               flangeFoundAndAdded = true;
549               addGroup = true;
550               aGroup->SetName("FLANGE");
551             }
552           }
553
554           // tuyau incident
555           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
556               (Abs(y) > aR2Ext + Precision::Confusion())) {
557             incidentPipeFound = false;
558           }
559           Ex.Next();
560         }
561         if (mainPipeFound) {
562           addGroup = true;
563           aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
564         }
565         if (incidentPipeFound) {
566           addGroup = true;
567           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
568         }
569         if (!addGroup && (!incidentPipeFound &&
570                           !mainPipeFound &&
571                           !flangeFound &&
572                           !chamferOrFilletFound)) {
573           addGroup = true;
574           chamferOrFilletFound = true;
575           if (shapeType == TSHAPE_CHAMFER)
576             aGroup->SetName("CHAMFER");
577           else
578             aGroup->SetName("FILLET");
579         }
580       }
581       else
582         continue;
583     }
584     // Add group to the list
585     if (addGroup)
586       theSeq->Append(aGroup);
587   }
588
589   SetErrorCode(OK);
590   return true;
591 }
592
593 bool GEOMImpl_IAdvancedOperations::MakePipeTShapePartition(Handle(GEOM_Object) theShape,
594                                                            double theR1, double theW1, double theL1,
595                                                            double theR2, double theW2, double theL2,
596                                                            double theH, double theW,
597                                                            double theRF, bool isNormal)
598 {
599   SetErrorCode(KO);
600
601   // Build tools for partition operation:
602   // 1 face and 2 planes
603   // Face
604   Handle(GEOM_Object) arete_intersect_int;
605   Handle(GEOM_Object) wire_t, wire_t2, face_t, face_t2;
606   Handle(GEOM_Object) chan_racc;
607   Handle(GEOM_Object) vi1, vi2;
608
609   Handle(GEOM_Object) Vector_Z = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
610   Vector_Z->GetLastFunction()->SetDescription("");
611
612   // Useful values
613   double aSize = 2*(theL1 + theL2);
614   double aR1Ext = theR1 + theW1;
615   double aR2Ext = theR2 + theW2;
616   double theVertCylinderRadius = aR2Ext + theW + theRF;
617   double theHoriCylinderRadius = aR1Ext + theH + theRF;
618
619   // Common edges on internal cylinder
620   Handle(GEOM_Object) box_i = my3DPrimOperations->MakeBoxDXDYDZ(theR2, theR2, theR1);
621   box_i->GetLastFunction()->SetDescription("");
622   box_i = myTransformOperations->TranslateDXDYDZ(box_i, -theR2, -theR2, 0);
623   box_i->GetLastFunction()->SetDescription("");
624
625   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
626   TCollection_AsciiString theDesc = aFunction->GetDescription();
627   Handle(TColStd_HSequenceOfTransient) edges_i =
628     myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
629   // Recover previous description to get rid of Propagate dump
630   aFunction->SetDescription(theDesc);
631   if (edges_i.IsNull() || edges_i->Length() == 0) {
632     SetErrorCode("Internal edges not found");
633     return false;
634   }
635   for (int i=1; i<=edges_i->Length();i++) {
636     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_i->Value(i));
637     anObj->GetLastFunction()->SetDescription("");
638   }
639   arete_intersect_int = Handle(GEOM_Object)::DownCast(edges_i->Value(1));
640
641   // search for vertices located on both internal pipes
642   aFunction = theShape->GetLastFunction();
643   theDesc = aFunction->GetDescription();
644   Handle(TColStd_HSequenceOfTransient) vertices_i =
645     myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
646   // Recover previous description to get rid of Propagate dump
647   aFunction->SetDescription(theDesc);
648   if (vertices_i.IsNull() || vertices_i->Length() == 0) {
649     SetErrorCode("Internal vertices not found");
650     return false;
651   }
652
653   for (int i = 1; i <= vertices_i->Length(); i++) {
654     Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_i->Value(i));
655     v->GetLastFunction()->SetDescription("");
656     TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
657     gp_Pnt aP = BRep_Tool::Pnt(aVertex);
658     if (Abs(aP.X()) <= Precision::Confusion()) {
659       if (Abs(aP.Y()) - theR2 <= Precision::Confusion())
660         vi1 = v;
661     } else if (Abs(aP.Y()) <= Precision::Confusion()) {
662       if (Abs(aP.X()) - theR1 <= Precision::Confusion())
663         vi2 = v;
664     }
665   }
666
667   std::list<Handle(GEOM_Object)> theShapes;
668
669   if (isNormal) {
670     Handle(GEOM_Object) ve1, ve2;
671
672     Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ(aR2Ext, aR2Ext, aR1Ext);
673     box_e->GetLastFunction()->SetDescription("");
674     box_e = myTransformOperations->TranslateDXDYDZ(box_e, -aR2Ext, -aR2Ext, 0);
675     box_e->GetLastFunction()->SetDescription("");
676     // Common edges on external cylinder
677     aFunction = theShape->GetLastFunction();
678     theDesc = aFunction->GetDescription();
679     Handle(TColStd_HSequenceOfTransient) edges_e =
680       myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
681     // Recover previous description to get rid of Propagate dump
682     aFunction->SetDescription(theDesc);
683     if (edges_e.IsNull() || edges_e->Length() == 0) {
684       SetErrorCode("External edges not found");
685       return false;
686     }
687     for (int i=1; i<=edges_e->Length();i++) {
688       Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
689       anObj->GetLastFunction()->SetDescription("");
690     }
691
692     // search for vertices located on both external pipes
693     aFunction = theShape->GetLastFunction();
694     theDesc = aFunction->GetDescription();
695     Handle(TColStd_HSequenceOfTransient) vertices_e =
696       myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
697     // Recover previous description to get rid of Propagate dump
698     aFunction->SetDescription(theDesc);
699     if (vertices_e.IsNull() || vertices_e->Length() == 0) {
700       SetErrorCode("External vertices not found");
701       return false;
702     }
703
704     for (int i = 1; i <= vertices_e->Length(); i++) {
705       Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_e->Value(i));
706       v->GetLastFunction()->SetDescription("");
707       TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
708       gp_Pnt aP = BRep_Tool::Pnt(aVertex);
709       if (Abs(aP.X()) <= Precision::Confusion()) {
710         if (Abs(aP.Y()) - theR2 > Precision::Confusion())
711           ve1 = v;
712       } else if (Abs(aP.Y()) <= Precision::Confusion()) {
713         if (Abs(aP.X()) - theR2 > Precision::Confusion())
714           ve2 = v;
715       }
716     }
717     Handle(GEOM_Object) edge_e1, edge_e2;
718     try {
719 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
720       OCC_CATCH_SIGNALS;
721 #endif
722       edge_e1 = myBasicOperations->MakeLineTwoPnt(ve1, vi1);
723       if (edge_e1.IsNull()) {
724         SetErrorCode("Edge 1 could not be built");
725         return false;
726       }
727     } catch (Standard_Failure) {
728       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
729       SetErrorCode(aFail->GetMessageString());
730       return false;
731     }
732
733     try {
734 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
735       OCC_CATCH_SIGNALS;
736 #endif
737       edge_e2 = myBasicOperations->MakeLineTwoPnt(ve2, vi2);
738       if (edge_e2.IsNull()) {
739         SetErrorCode("Edge 2 could not be built");
740         return false;
741       }
742     } catch (Standard_Failure) {
743       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
744       SetErrorCode(aFail->GetMessageString());
745       return false;
746     }
747
748     edge_e1->GetLastFunction()->SetDescription("");
749     edge_e2->GetLastFunction()->SetDescription("");
750
751     std::list<Handle(GEOM_Object)> edge_e_elist;
752     edge_e_elist.push_back(arete_intersect_int);
753     edge_e_elist.push_back(edge_e1);
754     edge_e_elist.push_back(Handle(GEOM_Object)::DownCast(edges_e->Value(1)));
755     edge_e_elist.push_back(edge_e2);
756     wire_t = myShapesOperations->MakeWire(edge_e_elist, 1e-7);
757     if (wire_t.IsNull()) {
758       SetErrorCode("Impossible to build wire");
759       return false;
760     }
761     wire_t->GetLastFunction()->SetDescription("");
762     face_t = myShapesOperations->MakeFace(wire_t, false);
763     if (face_t.IsNull()) {
764       SetErrorCode("Impossible to build face");
765       return false;
766     }
767     face_t->GetLastFunction()->SetDescription("");
768   }
769   else {
770     Handle(GEOM_Object) P1, P2, P3, P4, P5, P6;
771     int idP1, idP2, idP3, idP4;
772     int PZX, PZY;
773     double ZX=0, ZY=0;
774     std::vector<int> LX;
775     std::vector<int> LY;
776     Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ
777       (theVertCylinderRadius, theVertCylinderRadius, theHoriCylinderRadius);
778     box_e->GetLastFunction()->SetDescription("");
779     box_e = myTransformOperations->TranslateDXDYDZ
780       (box_e, -theVertCylinderRadius, -theVertCylinderRadius, 0);
781     box_e->GetLastFunction()->SetDescription("");
782
783     aFunction = theShape->GetLastFunction();
784     theDesc = aFunction->GetDescription();
785     Handle(TColStd_HSequenceOfTransient) extremVertices =
786       myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
787     // Recover previous description to get rid of Propagate dump
788     aFunction->SetDescription(theDesc);
789
790     if (extremVertices.IsNull() || extremVertices->Length() == 0) {
791       if (theRF == 0)
792         SetErrorCode("Vertices on chamfer not found");
793       else
794         SetErrorCode("Vertices on fillet not found");
795       return false;
796     }
797
798     theShapes.push_back(theShape);
799     theShapes.push_back(box_e);
800     if (extremVertices->Length() != 6) {
801       //           for (int i=1; i<=extremVertices->Length(); i++){
802       //             theShapes.push_back(Handle(GEOM_Object)::DownCast(extremVertices->Value(i)));
803       //           }
804       //           Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
805       //           TopoDS_Shape aCompoundShape = aCompound->GetValue();
806       //           theShape->GetLastFunction()->SetValue(aCompoundShape);
807       SetErrorCode("Bad number of vertices on chamfer found");
808       return false;
809     }
810
811     for (int i=1; i<=extremVertices->Length(); i++){
812       Handle(GEOM_Object) aV = Handle(GEOM_Object)::DownCast(extremVertices->Value(i));
813       aV->GetLastFunction()->SetDescription("");
814       gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aV->GetValue()));
815
816       if (Abs(aP.X()) <= Precision::Confusion()) {
817         if (Abs(aP.Y()) - theR2 > Precision::Confusion()) {
818           LX.push_back(i);
819           if  (aP.Z()-ZX > Precision::Confusion()) {
820             ZX = aP.Z();
821             PZX = i;
822           }
823         }
824       }
825       else {
826         if (Abs(aP.X()) - theR2 > Precision::Confusion()) {
827           LY.push_back(i);
828           if (aP.Z() - ZY > Precision::Confusion()) {
829             ZY = aP.Z();
830             PZY = i;
831           }
832         }
833       }
834     }
835
836     idP2 = PZX;
837     idP4 = PZY;
838     idP1 = LX.at(0);
839     if (LX.at(0) == PZX)
840       idP1 = LX.at(1);
841     idP3 = LY.at(0);
842     if (LY.at(0) == PZY)
843       idP3 = LY.at(1);
844
845     P1 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP1));
846     P2 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP2));
847     P3 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP3));
848     P4 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP4));
849
850     Handle(GEOM_Object) Cote_1 = myBasicOperations->MakeLineTwoPnt(P1, vi1);
851     if (Cote_1.IsNull()) {
852       SetErrorCode("Impossible to build edge in thickness");
853       return false;
854     }
855     Cote_1->GetLastFunction()->SetDescription("");
856
857     Handle(GEOM_Object) Cote_2 = myBasicOperations->MakeLineTwoPnt(vi2, P3);
858     if (Cote_2.IsNull()) {
859       SetErrorCode("Impossible to build edge in thickness");
860       return false;
861     }
862     Cote_2->GetLastFunction()->SetDescription("");
863
864     // edge_chan_princ = arete du chanfrein (ou raccord) sur le tuyau principal
865     // edge_chan_inc = arete du chanfrein (ou raccord) sur le tuyau incident
866     //         std::cerr << "Getting chamfer edge on main pipe" << std::endl;
867     Handle(GEOM_Object) edge_chan_princ = myBlocksOperations->GetEdge(theShape, P1, P3);
868     if (edge_chan_princ.IsNull()) {
869       SetErrorCode("Impossible to find edge on main pipe");
870       return false;
871     }
872     edge_chan_princ->GetLastFunction()->SetDescription("");
873
874     Handle(GEOM_Object) edge_chan_inc = myBlocksOperations->GetEdge(theShape, P2, P4);
875     if (edge_chan_inc.IsNull()) {
876       SetErrorCode("Impossible to find edge on incident pipe");
877       return false;
878     }
879     edge_chan_inc->GetLastFunction()->SetDescription("");
880
881     std::list<Handle(GEOM_Object)> edgeList1;
882     edgeList1.push_back(edge_chan_princ);
883     edgeList1.push_back(Cote_1);
884     edgeList1.push_back(arete_intersect_int);
885     edgeList1.push_back(Cote_2);
886
887     //         std::cerr << "Creating wire 1" << std::endl;
888     wire_t = myShapesOperations->MakeWire(edgeList1, 1e-7);
889     if (wire_t.IsNull()) {
890       SetErrorCode("Impossible to build wire");
891       return false;
892     }
893     wire_t->GetLastFunction()->SetDescription("");
894
895     //         std::cerr << "Creating face 1" << std::endl;
896     face_t = myShapesOperations->MakeFace(wire_t, false);
897     if (face_t.IsNull()) {
898       SetErrorCode("Impossible to build face");
899       return false;
900     }
901     face_t->GetLastFunction()->SetDescription("");
902     theShapes.push_back(face_t);
903
904     gp_Pnt aP2 = BRep_Tool::Pnt(TopoDS::Vertex(P2->GetValue()));
905     gp_Pnt aP5 = BRep_Tool::Pnt(TopoDS::Vertex(vi1->GetValue()));
906     double deltaZ = aP2.Z() - aP5.Z();
907     //         std::cerr << "Creating new point from vi1 with deltaZ = " << deltaZ << std::endl;
908     Handle(GEOM_Object) P5bis = myTransformOperations->TranslateDXDYDZCopy(vi1, 0, 0, deltaZ);
909     if (P5bis.IsNull()) {
910       SetErrorCode("Impossible to translate vertex");
911       return false;
912     }
913     P5bis->GetLastFunction()->SetDescription("");
914
915     gp_Pnt aP4 = BRep_Tool::Pnt(TopoDS::Vertex(P4->GetValue()));
916     gp_Pnt aP6 = BRep_Tool::Pnt(TopoDS::Vertex(vi2->GetValue()));
917     deltaZ = aP4.Z() - aP6.Z();
918     //         std::cerr << "Creating new point from vi2 with deltaZ = " << deltaZ << std::endl;
919     Handle(GEOM_Object) P6bis = myTransformOperations->TranslateDXDYDZCopy(vi2, 0, 0, deltaZ);
920     if (P6bis.IsNull()) {
921       SetErrorCode("Impossible to translate vertex");
922       return false;
923     }
924     P6bis->GetLastFunction()->SetDescription("");
925
926     //         std::cerr << "Creating new line 1 from 2 previous points" << std::endl;
927     Handle(GEOM_Object) Cote_3 = myBasicOperations->MakeLineTwoPnt(P5bis, P2);
928     if (Cote_3.IsNull()) {
929       SetErrorCode("Impossible to build edge in thickness");
930       return false;
931     }
932     Cote_3->GetLastFunction()->SetDescription("");
933
934     //         std::cerr << "Creating new line 2 from 2 previous points" << std::endl;
935     Handle(GEOM_Object) Cote_4 = myBasicOperations->MakeLineTwoPnt(P6bis, P4);
936     if (Cote_4.IsNull()) {
937       SetErrorCode("Impossible to build edge in thickness");
938       return false;
939     }
940     Cote_4->GetLastFunction()->SetDescription("");
941
942     //         std::cerr << "Creating new line 3 from 2 previous points" << std::endl;
943     Handle(GEOM_Object) Cote_5 = myBasicOperations->MakeLineTwoPnt(P5bis, P6bis);
944     if (Cote_4.IsNull()) {
945       SetErrorCode("Impossible to build edge in thickness");
946       return false;
947     }
948     Cote_5->GetLastFunction()->SetDescription("");
949
950     std::list<Handle(GEOM_Object)> edgeList2;
951     edgeList2.push_back(edge_chan_inc);
952     edgeList2.push_back(Cote_3);
953     edgeList2.push_back(Cote_5);
954     edgeList2.push_back(Cote_4);
955     //         std::cerr << "Creating wire 2" << std::endl;
956     //wire_t2 = myShapesOperations->MakeWire(edgeList2, 1e-7);
957     //if (wire_t2.IsNull()) {
958     //  SetErrorCode("Impossible to build wire");
959     //  return false;
960     //}
961     //wire_t2->GetLastFunction()->SetDescription("");
962     //         std::cerr << "Creating face 2" << std::endl;
963     //face_t2 = myShapesOperations->MakeFace(wire_t2, false);
964     face_t2 = my3DPrimOperations->MakePrismVecH(edge_chan_inc, Cote_4, - 2.0*theR2);
965     if (face_t2.IsNull()) {
966       SetErrorCode("Impossible to build face");
967       return false;
968     }
969     face_t2->GetLastFunction()->SetDescription("");
970     theShapes.push_back(face_t2);
971   }
972
973   // Planes
974   Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
975   Handle(GEOM_Object) aVZ = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
976   Handle(GEOM_Object) aVXZ = myBasicOperations->MakeVectorDXDYDZ(aR1Ext, 0, 0.5*(theL1+theVertCylinderRadius));
977   Handle(GEOM_Object) aPlnOZ = myBasicOperations->MakePlanePntVec(aP0, aVZ, aSize);
978   Handle(GEOM_Object) aPlnOXZ = myBasicOperations->MakePlanePntVec(aP0, aVXZ, aSize);
979   aP0->GetLastFunction()->SetDescription("");
980   aVZ->GetLastFunction()->SetDescription("");
981   aVXZ->GetLastFunction()->SetDescription("");
982   aPlnOZ->GetLastFunction()->SetDescription("");
983   aPlnOXZ->GetLastFunction()->SetDescription("");
984   theShapes.push_back(aPlnOZ);
985   theShapes.push_back(aPlnOXZ);
986
987   // tmp
988   /*
989   BRepTools::Write(theShape->GetValue(),
990                    "/dn25/salome/jfa/DATA/Salome/BUGS/M_0020998_Some_limitations_to_the_PipeTShape/theShape.brep");
991   BRepTools::Write(aPlnOZ->GetValue(),
992                    "/dn25/salome/jfa/DATA/Salome/BUGS/M_0020998_Some_limitations_to_the_PipeTShape/aPlnOZ.brep");
993   BRepTools::Write(aPlnOXZ->GetValue(),
994                    "/dn25/salome/jfa/DATA/Salome/BUGS/M_0020998_Some_limitations_to_the_PipeTShape/aPlnOXZ.brep");
995   BRepTools::Write(face_t->GetValue(),
996                    "/dn25/salome/jfa/DATA/Salome/BUGS/M_0020998_Some_limitations_to_the_PipeTShape/face_t.brep");
997   BRepTools::Write(face_t2->GetValue(),
998                    "/dn25/salome/jfa/DATA/Salome/BUGS/M_0020998_Some_limitations_to_the_PipeTShape/face_t2.brep");
999   */
1000
1001   // Partition
1002   Handle(TColStd_HSequenceOfTransient) partitionShapes = new TColStd_HSequenceOfTransient;
1003   Handle(TColStd_HSequenceOfTransient) theTools = new TColStd_HSequenceOfTransient;
1004   Handle(TColStd_HSequenceOfTransient) theKeepInside = new TColStd_HSequenceOfTransient;
1005   Handle(TColStd_HSequenceOfTransient) theRemoveInside = new TColStd_HSequenceOfTransient;
1006   Handle(TColStd_HArray1OfInteger) theMaterials;
1007   partitionShapes->Append(theShape);
1008   theTools->Append(aPlnOZ);
1009   if (Abs(aR1Ext - aR2Ext) > Precision::Confusion() )
1010     theTools->Append(aPlnOXZ);
1011   theTools->Append(face_t);
1012   if (!isNormal)
1013     theTools->Append(face_t2);
1014
1015   Handle(GEOM_Object) Te3 = myBooleanOperations->MakePartition
1016     (partitionShapes, theTools, theKeepInside, theRemoveInside,
1017      TopAbs_SOLID, false, theMaterials, 0, false);
1018   if (Te3.IsNull()) {
1019     SetErrorCode("Impossible to build partition of TShape");
1020     //         Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1021     //         TopoDS_Shape aCompoundShape = aCompound->GetValue();
1022     //         theShape->GetLastFunction()->SetValue(aCompoundShape);
1023     return false;
1024   }
1025   Te3->GetLastFunction()->SetDescription("");
1026
1027   // Last verification: result should be a block
1028   std::list<GEOMImpl_IBlocksOperations::BCError> errList;
1029   if (!myBlocksOperations->CheckCompoundOfBlocks(Te3,errList)) {
1030     SetErrorCode("TShape is not a block");
1031     return false;
1032   }
1033   TopoDS_Shape aShape = Te3->GetValue();
1034   theShape->GetLastFunction()->SetValue(aShape);
1035
1036   SetErrorCode(OK);
1037   return true;
1038 }
1039
1040 // Mirror and glue faces
1041 bool GEOMImpl_IAdvancedOperations::MakePipeTShapeMirrorAndGlue(Handle(GEOM_Object) theShape,
1042                                                                double theR1, double theW1, double theL1,
1043                                                                double theR2, double theW2, double theL2)
1044 {
1045   SetErrorCode(KO);
1046
1047   // Useful values
1048   double aSize = 2*(theL1 + theL2);
1049   double aR1Ext = theR1 + theW1;
1050
1051   // Planes
1052   Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1053   aP0->GetLastFunction()->SetDescription("");
1054   Handle(GEOM_Object) aVX = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
1055   Handle(GEOM_Object) aVY = myBasicOperations->MakeVectorDXDYDZ(0, 1, 0);
1056   aVX->GetLastFunction()->SetDescription("");
1057   aVY->GetLastFunction()->SetDescription("");
1058   Handle(GEOM_Object) aPlane_OX = myBasicOperations->MakePlanePntVec(aP0, aVX, 2*(aR1Ext + theL2));
1059   Handle(GEOM_Object) aPlane_OY = myBasicOperations->MakePlanePntVec(aP0, aVY, aSize);
1060   aPlane_OX->GetLastFunction()->SetDescription("");
1061   aPlane_OY->GetLastFunction()->SetDescription("");
1062
1063   Handle(GEOM_Object) Te4 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OX);
1064   if (Te4.IsNull()) {
1065     SetErrorCode("Impossible to build mirror of quarter TShape");
1066     return false;
1067   }
1068
1069   Handle(GEOM_Object) Te5 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OY);
1070   if (Te5.IsNull()) {
1071     SetErrorCode("Impossible to build mirror of half TShape");
1072     return false;
1073   }
1074
1075   Handle(GEOM_Object) Te6 = myTransformOperations->MirrorPlaneCopy(Te4, aPlane_OY);
1076   if (Te6.IsNull()) {
1077     SetErrorCode("Impossible to build mirror of half TShape");
1078     return false;
1079   }
1080
1081   std::list<Handle(GEOM_Object)> aShapesList;
1082   aShapesList.push_back(theShape);
1083   aShapesList.push_back(Te4);
1084   aShapesList.push_back(Te5);
1085   aShapesList.push_back(Te6);
1086   Handle(GEOM_Object) Te7 = myShapesOperations->MakeCompound(aShapesList);
1087   if (Te7.IsNull()) {
1088     SetErrorCode("Impossible to build compound");
1089     return false;
1090   }
1091
1092   Handle(GEOM_Object) Te8 = myShapesOperations->MakeGlueFaces(Te7, 1e-7, true);
1093   if (Te8.IsNull()) {
1094     SetErrorCode("Impossible to glue faces of TShape");
1095     return false;
1096   }
1097
1098   TopoDS_Shape aShape = Te8->GetValue();
1099
1100   theShape->GetLastFunction()->SetValue(aShape);
1101
1102   Te4->GetLastFunction()->SetDescription("");
1103   Te5->GetLastFunction()->SetDescription("");
1104   Te6->GetLastFunction()->SetDescription("");
1105   Te7->GetLastFunction()->SetDescription("");
1106   Te8->GetLastFunction()->SetDescription("");
1107
1108   SetErrorCode(OK);
1109   return true;
1110 }
1111
1112 //=============================================================================
1113 /*!
1114  *  MakePipeTShape
1115  *  Create a T-shape object with specified caracteristics for the main and
1116  *  the incident pipes (radius, width, half-length).
1117  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1118  *  \param theR1 Internal radius of main pipe
1119  *  \param theW1 Width of main pipe
1120  *  \param theL1 Half-length of main pipe
1121  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1122  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1123  *  \param theL2 Half-length of incident pipe
1124  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1125  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1126  */
1127 //=============================================================================
1128 Handle(TColStd_HSequenceOfTransient)
1129 GEOMImpl_IAdvancedOperations::MakePipeTShape(double theR1, double theW1, double theL1,
1130                                              double theR2, double theW2, double theL2,
1131                                              bool theHexMesh)
1132 {
1133   MESSAGE("GEOMImpl_IAdvancedOperations::MakePipeTShape");
1134   SetErrorCode(KO);
1135   //Add a new object
1136   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1137
1138   //Add a new shape function with parameters
1139   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1140   if (aFunction.IsNull()) return NULL;
1141
1142   //Check if the function is set correctly
1143   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1144
1145   GEOMImpl_IPipeTShape aData(aFunction);
1146
1147   aData.SetR1(theR1);
1148   aData.SetW1(theW1);
1149   aData.SetL1(theL1);
1150   aData.SetR2(theR2);
1151   aData.SetW2(theW2);
1152   aData.SetL2(theL2);
1153   aData.SetHexMesh(theHexMesh);
1154
1155   //Compute the resulting value
1156   try {
1157 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1158     OCC_CATCH_SIGNALS;
1159 #endif
1160     if (!GetSolver()->ComputeFunction(aFunction)) {
1161       SetErrorCode("TShape driver failed");
1162       return NULL;
1163     }
1164   } catch (Standard_Failure) {
1165     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1166     SetErrorCode(aFail->GetMessageString());
1167     return NULL;
1168   }
1169
1170   if (theHexMesh) {
1171     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1172       return NULL;
1173     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1174       return NULL;
1175   }
1176
1177   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1178   aSeq->Append(aShape);
1179
1180   if (theHexMesh) {
1181     /*
1182      * Get the groups: BEGIN
1183      */
1184     try {
1185       if (!MakeGroups(aShape, TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf()))
1186         return NULL;
1187     }
1188     catch (Standard_Failure) {
1189       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1190       SetErrorCode(aFail->GetMessageString());
1191       return NULL;
1192     }
1193
1194     TCollection_AsciiString aListRes, anEntry;
1195     // Iterate over the sequence aSeq
1196     Standard_Integer aNbGroups = aSeq->Length();
1197     Standard_Integer i = 2;
1198     for (; i <= aNbGroups; i++) {
1199       Handle(Standard_Transient) anItem = aSeq->Value(i);
1200       if (anItem.IsNull()) continue;
1201       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1202       if (aGroup.IsNull()) continue;
1203       //Make a Python command
1204       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1205       aListRes += anEntry + ", ";
1206     }
1207
1208     aListRes.Trunc(aListRes.Length() - 2);
1209
1210     //Make a Python command
1211     GEOM::TPythonDump(aFunction)
1212       << "[" << aShape << ", " << aListRes.ToCString() << "] = geompy.MakePipeTShape("
1213       << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", "
1214       << theHexMesh << ")";
1215   }
1216   /*
1217    * Get the groups: END
1218    */
1219   else {
1220     //Make a Python command
1221     GEOM::TPythonDump(aFunction)
1222       << "[" << aShape << "] = geompy.MakePipeTShape(" << theR1 << ", " << theW1 << ", "
1223       << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theHexMesh << ")";
1224   }
1225
1226   SetErrorCode(OK);
1227
1228   return aSeq;
1229 }
1230
1231 //=============================================================================
1232 /*!
1233  *  MakePipeTShapeWithPosition
1234  *  Create a T-shape object with specified caracteristics for the main and
1235  *  the incident pipes (radius, width, half-length).
1236  *  The extremities of the main pipe are located on junctions points P1 and P2.
1237  *  The extremity of the incident pipe is located on junction point P3.
1238  *  \param theR1 Internal radius of main pipe
1239  *  \param theW1 Width of main pipe
1240  *  \param theL1 Half-length of main pipe
1241  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1242  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1243  *  \param theL2 Half-length of incident pipe
1244  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1245  *  \param theP1 1st junction point of main pipe
1246  *  \param theP2 2nd junction point of main pipe
1247  *  \param theP3 Junction point of incident pipe
1248  *  \return List of GEOM_Objects, containing the created shape and propagation groups..
1249  */
1250 //=============================================================================
1251 Handle(TColStd_HSequenceOfTransient)
1252 GEOMImpl_IAdvancedOperations::MakePipeTShapeWithPosition(double theR1, double theW1, double theL1,
1253                                                          double theR2, double theW2, double theL2,
1254                                                          bool theHexMesh,
1255                                                          Handle(GEOM_Object) theP1,
1256                                                          Handle(GEOM_Object) theP2,
1257                                                          Handle(GEOM_Object) theP3)
1258 {
1259   SetErrorCode(KO);
1260   //Add a new object
1261   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1262   /////////////////
1263   // TSHAPE CODE
1264   /////////////////
1265   //Add a new shape function with parameters
1266   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1267   if (aFunction.IsNull()) return NULL;
1268
1269   //Check if the function is set correctly
1270   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1271
1272   // Check new position
1273   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
1274     return NULL;
1275   }
1276
1277   GEOMImpl_IPipeTShape aData(aFunction);
1278
1279   aData.SetR1(theR1);
1280   aData.SetW1(theW1);
1281   aData.SetL1(theL1);
1282   aData.SetR2(theR2);
1283   aData.SetW2(theW2);
1284   aData.SetL2(theL2);
1285   aData.SetHexMesh(theHexMesh);
1286
1287   //Compute the resulting value
1288   try {
1289 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1290     OCC_CATCH_SIGNALS;
1291 #endif
1292     if (!GetSolver()->ComputeFunction(aFunction)) {
1293       SetErrorCode("TShape driver failed");
1294       return NULL;
1295     }
1296   } catch (Standard_Failure) {
1297     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1298     SetErrorCode(aFail->GetMessageString());
1299     return NULL;
1300   }
1301
1302   if (theHexMesh) {
1303     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1304       return NULL;
1305     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1306       return NULL;
1307   }
1308
1309   TopoDS_Shape Te = aShape->GetValue();
1310
1311   // Set Position
1312   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
1313   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
1314   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
1315   aFunction->SetValue(aTrsf_Shape);
1316   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1317   aSeq->Append(aShape);
1318
1319   if (theHexMesh) {
1320     //
1321     // Get the groups: BEGIN
1322     //
1323     try {
1324       if (!MakeGroups(aShape,TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf)) {
1325         return NULL;
1326       }
1327     }
1328     catch (Standard_Failure) {
1329       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1330       SetErrorCode(aFail->GetMessageString());
1331       return NULL;
1332     }
1333
1334     TCollection_AsciiString aListRes, anEntry;
1335     // Iterate over the sequence aSeq
1336     Standard_Integer aNbGroups = aSeq->Length();
1337     Standard_Integer i = 2;
1338     for (; i <= aNbGroups; i++) {
1339       Handle(Standard_Transient) anItem = aSeq->Value(i);
1340       if (anItem.IsNull()) continue;
1341       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1342       if (aGroup.IsNull()) continue;
1343       //Make a Python command
1344       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1345       aListRes += anEntry + ", ";
1346     }
1347
1348     aListRes.Trunc(aListRes.Length() - 2);
1349
1350     //Make a Python command
1351     GEOM::TPythonDump(aFunction)
1352       << "[" << aShape << ", " << aListRes.ToCString() << "] = geompy.MakePipeTShape("
1353       << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", "
1354       << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
1355   }
1356   //
1357   // Get the groups: END
1358   //
1359
1360   else {
1361     //Make a Python command
1362     GEOM::TPythonDump(aFunction)
1363       << "[" << aShape << "] = geompy.MakePipeTShape(" << theR1 << ", " << theW1 << ", "
1364       << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theHexMesh << ", " << theP1
1365       << ", " << theP2 << ", " << theP3 << ")";
1366   }
1367
1368   SetErrorCode(OK);
1369
1370   return aSeq;
1371 }
1372
1373 //=============================================================================
1374 /*!
1375  *  MakePipeTShapeChamfer
1376  *  Create a T-shape object with specified caracteristics for the main and
1377  *  the incident pipes (radius, width, half-length). A chamfer is created
1378  *  on the junction of the pipes.
1379  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1380  *  \param theR1 Internal radius of main pipe
1381  *  \param theW1 Width of main pipe
1382  *  \param theL1 Half-length of main pipe
1383  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1384  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1385  *  \param theL2 Half-length of incident pipe
1386  *  \param theH Height of chamfer.
1387  *  \param theW Width of chamfer.
1388  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1389  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1390  */
1391 //=============================================================================
1392 Handle(TColStd_HSequenceOfTransient)
1393 GEOMImpl_IAdvancedOperations::MakePipeTShapeChamfer(double theR1, double theW1, double theL1,
1394                                                     double theR2, double theW2, double theL2,
1395                                                     double theH, double theW,
1396                                                     bool theHexMesh)
1397 {
1398   SetErrorCode(KO);
1399   //Add a new object
1400   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1401   //Add a new shape function with parameters
1402   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
1403   if (aFunction.IsNull()) return NULL;
1404
1405   //Check if the function is set correctly
1406   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1407
1408   GEOMImpl_IPipeTShape aData(aFunction);
1409
1410   aData.SetR1(theR1);
1411   aData.SetW1(theW1);
1412   aData.SetL1(theL1);
1413   aData.SetR2(theR2);
1414   aData.SetW2(theW2);
1415   aData.SetL2(theL2);
1416   aData.SetH(theH);
1417   aData.SetW(theW);
1418   aData.SetHexMesh(theHexMesh);
1419
1420   //Compute the resulting value
1421   try {
1422 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1423     OCC_CATCH_SIGNALS;
1424 #endif
1425     if (!GetSolver()->ComputeFunction(aFunction)) {
1426       SetErrorCode("TShape driver failed");
1427       return NULL;
1428     }
1429   } catch (Standard_Failure) {
1430     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1431     SetErrorCode(aFail->GetMessageString());
1432     return NULL;
1433   }
1434
1435   // BEGIN of chamfer
1436   TopoDS_Shape aShapeShape = aShape->GetValue();
1437   TopTools_IndexedMapOfShape anEdgesIndices;
1438   TopExp::MapShapes(aShapeShape, anEdgesIndices);
1439   // Common edges on external cylinders
1440   Handle(GEOM_Object) box_e;
1441   if (theHexMesh) {
1442     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1443   }
1444   else {
1445     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1446   }
1447   box_e->GetLastFunction()->SetDescription("");
1448   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1449   box_e->GetLastFunction()->SetDescription("");
1450
1451   Handle(TColStd_HSequenceOfInteger) edges_e =
1452     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1453   box_e->GetLastFunction()->SetDescription("");
1454
1455   if (edges_e.IsNull() || edges_e->Length() == 0) {
1456     SetErrorCode("External edges not found");
1457     return false;
1458   }
1459   int nbEdgesInChamfer = 0;
1460   std::list<int> theEdges;
1461   for (int i=1; i<=edges_e->Length();i++) {
1462     int edgeID = edges_e->Value(i);
1463     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1464     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1465     int iv=0;
1466     while (Ex.More()) {
1467       iv ++;
1468       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1469       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1470         nbEdgesInChamfer ++;
1471         theEdges.push_back(edgeID);
1472       }
1473       Ex.Next();
1474     }
1475     if (theHexMesh && nbEdgesInChamfer == 1)
1476       break;
1477   }
1478   Handle(GEOM_Object) aChamfer;
1479   try {
1480     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
1481   }
1482   catch (Standard_Failure) {
1483     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1484     SetErrorCode(aFail->GetMessageString());
1485     return NULL;
1486   }
1487   if (aChamfer.IsNull()) {
1488     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
1489     return NULL;
1490   }
1491   aChamfer->GetLastFunction()->SetDescription("");
1492
1493   TopoDS_Shape aChamferShape = aChamfer->GetValue();
1494   aFunction->SetValue(aChamferShape);
1495   // END of chamfer
1496
1497   //   bool doMesh = false;
1498   if (theHexMesh) {
1499     //        doMesh = true;
1500     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false)) {
1501       MESSAGE("PipeTShape partition failed");
1502       //            doMesh = false;
1503       return NULL;
1504     }
1505     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2)) {
1506       MESSAGE("PipeTShape mirrors and glue failed");
1507       //          doMesh = false;
1508       return NULL;
1509     }
1510   }
1511
1512   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1513   aSeq->Append(aShape);
1514
1515   //    if (doMesh) {
1516   if (theHexMesh) {
1517     //
1518     //         Get the groups: BEGIN
1519     //
1520     //if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf())) {
1521     //  //Make a Python command
1522     //  GEOM::TPythonDump(aFunction)
1523     //    << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1524     //    << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1525     //    << ", " << theHexMesh << ")";
1526     //}
1527     //else {
1528     try {
1529       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf()))
1530         return NULL;
1531     }
1532     catch (Standard_Failure) {
1533       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1534       SetErrorCode(aFail->GetMessageString());
1535       return NULL;
1536     }
1537
1538     TCollection_AsciiString aListRes, anEntry;
1539     // Iterate over the sequence aSeq
1540     Standard_Integer aNbGroups = aSeq->Length();
1541     Standard_Integer i = 2;
1542     for (; i <= aNbGroups; i++) {
1543       Handle(Standard_Transient) anItem = aSeq->Value(i);
1544       if (anItem.IsNull()) continue;
1545       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1546       if (aGroup.IsNull()) continue;
1547       //Make a Python command
1548       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1549       aListRes += anEntry + ", ";
1550     }
1551
1552     aListRes.Trunc(aListRes.Length() - 2);
1553
1554     //Make a Python command
1555     GEOM::TPythonDump(aFunction)
1556       << "[" << aShape << ", " << aListRes.ToCString()
1557       << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1558       << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW << ", " << theHexMesh << ")";
1559     //}
1560   }
1561   //
1562   //     Get the groups: END
1563   //
1564   else {
1565     //Make a Python command
1566     GEOM::TPythonDump(aFunction)
1567       << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1568       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1569       << ", " << theHexMesh << ")";
1570   }
1571
1572   SetErrorCode(OK);
1573
1574   return aSeq;
1575 }
1576
1577 //=============================================================================
1578 /*!
1579  *  MakePipeTShapeChamferWithPosition
1580  *  Create a T-shape object with specified caracteristics for the main and
1581  *  the incident pipes (radius, width, half-length). A chamfer is created
1582  *  on the junction of the pipes.
1583  *  The extremities of the main pipe are located on junctions points P1 and P2.
1584  *  The extremity of the incident pipe is located on junction point P3.
1585  *  \param theR1 Internal radius of main pipe
1586  *  \param theW1 Width of main pipe
1587  *  \param theL1 Half-length of main pipe
1588  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1589  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1590  *  \param theL2 Half-length of incident pipe
1591  *  \param theH Height of chamfer.
1592  *  \param theW Width of chamfer.
1593  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1594  *  \param theP1 1st junction point of main pipe
1595  *  \param theP2 2nd junction point of main pipe
1596  *  \param theP3 Junction point of incident pipe
1597  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1598  */
1599 //=============================================================================
1600 Handle(TColStd_HSequenceOfTransient)
1601 GEOMImpl_IAdvancedOperations::MakePipeTShapeChamferWithPosition(double theR1, double theW1, double theL1,
1602                                                                 double theR2, double theW2, double theL2,
1603                                                                 double theH, double theW,
1604                                                                 bool theHexMesh,
1605                                                                 Handle(GEOM_Object) theP1,
1606                                                                 Handle(GEOM_Object) theP2,
1607                                                                 Handle(GEOM_Object) theP3)
1608 {
1609   SetErrorCode(KO);
1610   //Add a new object
1611   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1612   //Add a new shape function with parameters
1613   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
1614   if (aFunction.IsNull()) return NULL;
1615
1616   //Check if the function is set correctly
1617   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1618
1619   // Check new position
1620   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
1621     return NULL;
1622   }
1623
1624   GEOMImpl_IPipeTShape aData(aFunction);
1625
1626   aData.SetR1(theR1);
1627   aData.SetW1(theW1);
1628   aData.SetL1(theL1);
1629   aData.SetR2(theR2);
1630   aData.SetW2(theW2);
1631   aData.SetL2(theL2);
1632   aData.SetH(theH);
1633   aData.SetW(theW);
1634   aData.SetHexMesh(theHexMesh);
1635
1636   //Compute the resulting value
1637   try {
1638 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1639     OCC_CATCH_SIGNALS;
1640 #endif
1641     if (!GetSolver()->ComputeFunction(aFunction)) {
1642       SetErrorCode("TShape driver failed");
1643       return NULL;
1644     }
1645   } catch (Standard_Failure) {
1646     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1647     SetErrorCode(aFail->GetMessageString());
1648     return NULL;
1649   }
1650
1651   // BEGIN of chamfer
1652   TopoDS_Shape aShapeShape = aShape->GetValue();
1653   TopTools_IndexedMapOfShape anEdgesIndices;
1654   TopExp::MapShapes(aShapeShape, anEdgesIndices);
1655   // Common edges on external cylinders
1656   Handle(GEOM_Object) box_e;
1657   if (theHexMesh) {
1658     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1659   }
1660   else {
1661     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1662   }
1663   box_e->GetLastFunction()->SetDescription("");
1664   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1665   box_e->GetLastFunction()->SetDescription("");
1666
1667   Handle(TColStd_HSequenceOfInteger) edges_e =
1668     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1669   box_e->GetLastFunction()->SetDescription("");
1670
1671   if (edges_e.IsNull() || edges_e->Length() == 0) {
1672     SetErrorCode("External edges not found");
1673     return false;
1674   }
1675   int nbEdgesInChamfer = 0;
1676   std::list<int> theEdges;
1677   for (int i=1; i<=edges_e->Length();i++) {
1678     int edgeID = edges_e->Value(i);
1679     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1680     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1681     while (Ex.More()) {
1682       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1683       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1684         nbEdgesInChamfer ++;
1685         theEdges.push_back(edgeID);
1686       }
1687       Ex.Next();
1688     }
1689     if (theHexMesh && nbEdgesInChamfer == 1)
1690       break;
1691   }
1692   Handle(GEOM_Object) aChamfer;
1693   try {
1694     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
1695   }
1696   catch (Standard_Failure) {
1697     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1698     SetErrorCode(aFail->GetMessageString());
1699     return NULL;
1700   }
1701   if (aChamfer.IsNull()) {
1702     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
1703     return NULL;
1704   }
1705   aChamfer->GetLastFunction()->SetDescription("");
1706
1707   TopoDS_Shape aChamferShape = aChamfer->GetValue();
1708   aFunction->SetValue(aChamferShape);
1709   // END of chamfer
1710
1711   if (theHexMesh) {
1712     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
1713       return NULL;
1714     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1715       return NULL;
1716   }
1717
1718   TopoDS_Shape Te = aShape->GetValue();
1719
1720   // Set Position
1721   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
1722   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
1723   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
1724   aFunction->SetValue(aTrsf_Shape);
1725   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1726   aSeq->Append(aShape);
1727   if (theHexMesh) {
1728     /*
1729      * Get the groups: BEGIN
1730      */
1731     try {
1732       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf))
1733         return NULL;
1734     }
1735     catch (Standard_Failure) {
1736       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1737       SetErrorCode(aFail->GetMessageString());
1738       return NULL;
1739     }
1740
1741     TCollection_AsciiString aListRes, anEntry;
1742     // Iterate over the sequence aSeq
1743     Standard_Integer aNbGroups = aSeq->Length();
1744     Standard_Integer i = 2;
1745     for (; i <= aNbGroups; i++) {
1746       Handle(Standard_Transient) anItem = aSeq->Value(i);
1747       if (anItem.IsNull()) continue;
1748       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1749       if (aGroup.IsNull()) continue;
1750       //Make a Python command
1751       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1752       aListRes += anEntry + ", ";
1753     }
1754
1755     aListRes.Trunc(aListRes.Length() - 2);
1756
1757     //Make a Python command
1758     GEOM::TPythonDump(aFunction)
1759       << "[" << aShape << ", " << aListRes.ToCString()
1760       << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1761       << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW << ", " << theHexMesh << ", "
1762       << theP1 << ", " << theP2 << ", " << theP3 << ")";
1763   }
1764   /*
1765    * Get the groups: END
1766    */
1767   else {
1768     //Make a Python command
1769     GEOM::TPythonDump(aFunction)
1770       << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1771       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1772       << ", " << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
1773   }
1774
1775   SetErrorCode(OK);
1776
1777   return aSeq;
1778 }
1779
1780 //=============================================================================
1781 /*!
1782  *  MakePipeTShapeFillet
1783  *  Create a T-shape object with specified caracteristics for the main and
1784  *  the incident pipes (radius, width, half-length). A fillet is created
1785  *  on the junction of the pipes.
1786  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1787  *  \param theR1 Internal radius of main pipe
1788  *  \param theW1 Width of main pipe
1789  *  \param theL1 Half-length of main pipe
1790  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1791  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1792  *  \param theL2 Half-length of incident pipe
1793  *  \param theRF Radius of curvature of fillet.
1794  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1795  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1796  */
1797 //=============================================================================
1798 Handle(TColStd_HSequenceOfTransient)
1799 GEOMImpl_IAdvancedOperations::MakePipeTShapeFillet(double theR1, double theW1, double theL1,
1800                                                    double theR2, double theW2, double theL2,
1801                                                    double theRF, bool theHexMesh)
1802 {
1803   SetErrorCode(KO);
1804   //Add a new object
1805   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1806   //Add a new shape function with parameters
1807   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
1808   if (aFunction.IsNull()) return NULL;
1809
1810   //Check if the function is set correctly
1811   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1812
1813   GEOMImpl_IPipeTShape aData(aFunction);
1814
1815   aData.SetR1(theR1);
1816   aData.SetW1(theW1);
1817   aData.SetL1(theL1);
1818   aData.SetR2(theR2);
1819   aData.SetW2(theW2);
1820   aData.SetL2(theL2);
1821   aData.SetRF(theRF);
1822   aData.SetHexMesh(theHexMesh);
1823
1824   //Compute the resulting value
1825   try {
1826 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1827     OCC_CATCH_SIGNALS;
1828 #endif
1829     if (!GetSolver()->ComputeFunction(aFunction)) {
1830       SetErrorCode("TShape driver failed");
1831       return NULL;
1832     }
1833   } catch (Standard_Failure) {
1834     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1835     SetErrorCode(aFail->GetMessageString());
1836     return NULL;
1837   }
1838
1839   // BEGIN of fillet
1840   TopoDS_Shape aShapeShape = aShape->GetValue();
1841   TopTools_IndexedMapOfShape anEdgesIndices;
1842   TopExp::MapShapes(aShapeShape, anEdgesIndices);
1843   // Common edges on external cylinders
1844   Handle(GEOM_Object) box_e;
1845   if (theHexMesh) {
1846     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1847   }
1848   else {
1849     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1850   }
1851   box_e->GetLastFunction()->SetDescription("");
1852   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1853   box_e->GetLastFunction()->SetDescription("");
1854
1855   Handle(TColStd_HSequenceOfInteger) edges_e =
1856     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1857   box_e->GetLastFunction()->SetDescription("");
1858
1859   if (edges_e.IsNull() || edges_e->Length() == 0) {
1860     SetErrorCode("External edges not found");
1861     return false;
1862   }
1863   int nbEdgesInFillet = 0;
1864   std::list<int> theEdges;
1865   for (int i=1; i<=edges_e->Length();i++) {
1866     int edgeID = edges_e->Value(i);
1867     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1868     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1869     while (Ex.More()) {
1870       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1871       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1872         nbEdgesInFillet ++;
1873         theEdges.push_back(edgeID);
1874       }
1875       Ex.Next();
1876     }
1877     if (theHexMesh && nbEdgesInFillet == 1)
1878       break;
1879   }
1880
1881   Handle(GEOM_Object) aFillet;
1882   try {
1883     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
1884   }
1885   catch (Standard_Failure) {
1886     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1887     SetErrorCode(aFail->GetMessageString());
1888     return NULL;
1889   }
1890   if (aFillet.IsNull()) {
1891     //SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
1892     SetErrorCode(myLocalOperations->GetErrorCode());
1893     return NULL;
1894   }
1895   aFillet->GetLastFunction()->SetDescription("");
1896
1897   TopoDS_Shape aFilletShape = aFillet->GetValue();
1898   aFunction->SetValue(aFilletShape);
1899   // END of fillet
1900
1901   // BEGIN: Limit tolerances (debug)
1902   GEOMImpl_IHealingOperations myHealingOperations (GetEngine(), GetDocID());
1903
1904   Handle(GEOM_Object) aCorr1 = myHealingOperations.LimitTolerance(aShape, 1e-07);
1905   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
1906   aShape->GetLastFunction()->SetValue(aCorr1Shape);
1907   aCorr1->GetLastFunction()->SetDescription("");
1908   // END: Limit tolerances (debug)
1909
1910   if (theHexMesh) {
1911     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
1912       return NULL;
1913     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1914       return NULL;
1915   }
1916
1917   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1918   aSeq->Append(aShape);
1919   if (theHexMesh) {
1920     /*
1921      * Get the groups: BEGIN
1922      */
1923     try {
1924       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf()))
1925         return NULL;
1926     }
1927     catch (Standard_Failure) {
1928       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1929       SetErrorCode(aFail->GetMessageString());
1930       return NULL;
1931     }
1932
1933     TCollection_AsciiString aListRes, anEntry;
1934     // Iterate over the sequence aSeq
1935     Standard_Integer aNbGroups = aSeq->Length();
1936     Standard_Integer i = 2;
1937     for (; i <= aNbGroups; i++) {
1938       Handle(Standard_Transient) anItem = aSeq->Value(i);
1939       if (anItem.IsNull()) continue;
1940       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1941       if (aGroup.IsNull()) continue;
1942       //Make a Python command
1943       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1944       aListRes += anEntry + ", ";
1945     }
1946
1947     aListRes.Trunc(aListRes.Length() - 2);
1948
1949     //Make a Python command
1950     GEOM::TPythonDump(aFunction)
1951       << "[" << aShape << ", " << aListRes.ToCString()
1952       << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1953       << ", " << theW2 << ", " << theL2 << ", " << theRF << ", " << theHexMesh << ")";
1954   }
1955   /*
1956    * Get the groups: END
1957    */
1958   else {
1959     //Make a Python command
1960     GEOM::TPythonDump(aFunction)
1961       << "[" << aShape << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1
1962       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", "
1963       << theHexMesh << ")";
1964   }
1965
1966   SetErrorCode(OK);
1967
1968   return aSeq;
1969 }
1970
1971 //=============================================================================
1972 /*!
1973  *  MakePipeTShapeFilletWithPosition
1974  *  Create a T-shape object with specified caracteristics for the main and
1975  *  the incident pipes (radius, width, half-length). A fillet is created
1976  *  on the junction of the pipes.
1977  *  The extremities of the main pipe are located on junctions points P1 and P2.
1978  *  The extremity of the incident pipe is located on junction point P3.
1979  *  \param theR1 Internal radius of main pipe
1980  *  \param theW1 Width of main pipe
1981  *  \param theL1 Half-length of main pipe
1982  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1983  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1984  *  \param theL2 Half-length of incident pipe
1985  *  \param theRF Radius of curvature of fillet
1986  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1987  *  \param theP1 1st junction point of main pipe
1988  *  \param theP2 2nd junction point of main pipe
1989  *  \param theP3 Junction point of incident pipe
1990  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1991  */
1992 //=============================================================================
1993 Handle(TColStd_HSequenceOfTransient)
1994 GEOMImpl_IAdvancedOperations::MakePipeTShapeFilletWithPosition(double theR1, double theW1, double theL1,
1995                                                                double theR2, double theW2, double theL2,
1996                                                                double theRF, bool theHexMesh,
1997                                                                Handle(GEOM_Object) theP1,
1998                                                                Handle(GEOM_Object) theP2,
1999                                                                Handle(GEOM_Object) theP3)
2000 {
2001   SetErrorCode(KO);
2002   //Add a new object
2003   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2004   //Add a new shape function with parameters
2005   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2006   if (aFunction.IsNull()) return NULL;
2007
2008   //Check if the function is set correctly
2009   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
2010
2011   // Check new position
2012   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2013     return NULL;
2014   }
2015
2016   GEOMImpl_IPipeTShape aData(aFunction);
2017
2018   aData.SetR1(theR1);
2019   aData.SetW1(theW1);
2020   aData.SetL1(theL1);
2021   aData.SetR2(theR2);
2022   aData.SetW2(theW2);
2023   aData.SetL2(theL2);
2024   aData.SetRF(theRF);
2025   aData.SetHexMesh(theHexMesh);
2026
2027   //Compute the resulting value
2028   try {
2029 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2030     OCC_CATCH_SIGNALS;
2031 #endif
2032     if (!GetSolver()->ComputeFunction(aFunction)) {
2033       SetErrorCode("TShape driver failed");
2034       return NULL;
2035     }
2036   } catch (Standard_Failure) {
2037     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2038     SetErrorCode(aFail->GetMessageString());
2039     return NULL;
2040   }
2041
2042   // BEGIN of fillet
2043   TopoDS_Shape aShapeShape = aShape->GetValue();
2044   TopTools_IndexedMapOfShape anEdgesIndices;
2045   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2046   // Common edges on external cylinders
2047   Handle(GEOM_Object) box_e;
2048   if (theHexMesh) {
2049     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2050   }
2051   else {
2052     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2053   }
2054   box_e->GetLastFunction()->SetDescription("");
2055   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2056   box_e->GetLastFunction()->SetDescription("");
2057
2058   Handle(TColStd_HSequenceOfInteger) edges_e =
2059     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2060   box_e->GetLastFunction()->SetDescription("");
2061
2062   if (edges_e.IsNull() || edges_e->Length() == 0) {
2063     SetErrorCode("External edges not found");
2064     return false;
2065   }
2066   int nbEdgesInFillet = 0;
2067   std::list<int> theEdges;
2068   for (int i=1; i<=edges_e->Length();i++) {
2069     int edgeID = edges_e->Value(i);
2070     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2071     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2072     while (Ex.More()) {
2073       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2074       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2075         nbEdgesInFillet ++;
2076         theEdges.push_back(edgeID);
2077       }
2078       Ex.Next();
2079     }
2080     if (theHexMesh && nbEdgesInFillet == 1)
2081       break;
2082   }
2083
2084   Handle(GEOM_Object) aFillet;
2085   try {
2086     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
2087   }
2088   catch (Standard_Failure) {
2089     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2090     SetErrorCode(aFail->GetMessageString());
2091     return NULL;
2092   }
2093   if (aFillet.IsNull()) {
2094     SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
2095     return NULL;
2096   }
2097   aFillet->GetLastFunction()->SetDescription("");
2098
2099   TopoDS_Shape aFilletShape = aFillet->GetValue();
2100   aFunction->SetValue(aFilletShape);
2101   // END of fillet
2102
2103   if (theHexMesh) {
2104     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
2105       return NULL;
2106     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2107       return NULL;
2108   }
2109
2110   TopoDS_Shape Te = aShape->GetValue();
2111
2112   // Set Position
2113   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2114   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
2115   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2116   aFunction->SetValue(aTrsf_Shape);
2117   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2118   aSeq->Append(aShape);
2119   if (theHexMesh) {
2120     /*
2121      * Get the groups: BEGIN
2122      */
2123     try {
2124       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf))
2125         return NULL;
2126     }
2127     catch (Standard_Failure) {
2128       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2129       SetErrorCode(aFail->GetMessageString());
2130       return NULL;
2131     }
2132
2133     TCollection_AsciiString aListRes, anEntry;
2134     // Iterate over the sequence aSeq
2135     Standard_Integer aNbGroups = aSeq->Length();
2136     Standard_Integer i = 2;
2137     for (; i <= aNbGroups; i++) {
2138       Handle(Standard_Transient) anItem = aSeq->Value(i);
2139       if (anItem.IsNull()) continue;
2140       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2141       if (aGroup.IsNull()) continue;
2142       //Make a Python command
2143       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2144       aListRes += anEntry + ", ";
2145     }
2146
2147     aListRes.Trunc(aListRes.Length() - 2);
2148
2149     //Make a Python command
2150     GEOM::TPythonDump(aFunction)
2151       << "[" << aShape << ", " << aListRes.ToCString()
2152       << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
2153       << ", " << theW2 << ", " << theL2 << ", " << theRF << ", " << theHexMesh << ", " << theP1 << ", "
2154       << theP2 << ", " << theP3 << ")";
2155   }
2156   /*
2157    * Get the groups: END
2158    */
2159   else {
2160     //Make a Python command
2161     GEOM::TPythonDump(aFunction)
2162       << "[" << aShape << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1
2163       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", "
2164       << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
2165   }
2166
2167   SetErrorCode(OK);
2168
2169   return aSeq;
2170 }
2171
2172 /*@@ insert new functions before this line @@ do not remove this line @@ do not remove this line @@*/